前言
书接上文《Vue3中的 ref() 为何需要 .value ?》,我们已经完成了ref
函数,在这基础上实现isRef
和unref
这两个功能函数。
回顾一下ref
的实现代码,
class RefImpl {
private _value: any;
public dep;
private rawValue: any;
constructor(value) {
this.rawValue = value;
this._value = convert(value);
this.dep = new Set();
}
get value() {
if (isTracking()) trackEffects(this.dep);
return this._value;
}
set value(newValue) {
if (hasChanged(newValue, this.rawValue)) {
this.rawValue = newValue;
this._value = convert(newValue);
triggerEffects(this.dep);
}
}
}
function convert(value) {
return isObject(value) ? reactive(value) : value;
}
export function ref(value) {
return new RefImpl(value);
}
ref
函数返回的 class 类RefImpl
的实例对象,通过对象包裹实现对单值的数据拦截。在get操作时,调用trackEffects
收集依赖,将依赖存放在dep
中;set
操作时调用triggerEffects
触发dep
中依赖。
isRef()
isRef()
表示检查某个值是否为 ref
,返回一个布尔值。
单测
ref.spec.ts
中添加isRef
测试用例,
it("isRef", () => {
const a = ref(1);
const user = reactive({
name: "jack",
});
expect(isRef(a)).toBe(true);
expect(isRef(1)).toBe(false);
expect(isRef(user)).toBe(false);
});
如果是ref
类型的就断言为true
,如果是基本类型例如Number
类型或者reactive
类型就返回false
。
实现
基本思路:在RefImpl
类中定义一个公共属性__v_isRef
,但只有ref
类型访问时候才会有这个属性,其他类型访问时候是不存在的。
class RefImpl {
private _value: any;
public dep;
private rawValue: any;
public __v_isRef = true;
constructor(value) {
this.rawValue = value;
this._value = convert(value);
this.dep = new Set();
}
...
}
export function isRef(ref) {
return !!ref.__v_isRef;
}
执行单测yarn test ref
,进行验证。
unref
官方文档 的介绍:
如果参数是 ref,则返回内部值,否则返回参数本身。这是 val = isRef(val) ? val.value : val 计算的一个语法糖。
单测
ref.spec.ts
中添加unref
测试用例,
it("unref", () => {
const a = ref(1);
expect(unref(a)).toBe(1);
expect(unref(1)).toBe(1);
});
实现
export function unref(ref) {
return isRef(ref) ? ref.value : ref;
}
执行单测yarn test ref
,进行验证。
点个在看 ⬇⬇ 感谢感谢
原文始发于微信公众号(前端一起学):Vue3源码中 isRef & unref 也就两行代码
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/191250.html