1.ref函数
function ref(value) {
return createRef(value, false);
}
function createRef(rawValue, shallow) {
// 这里先判断是不是ref对象,是的话直接返回
if (isRef(rawValue)) {
return rawValue;
}
return new RefImpl(rawValue, shallow);
}
主要看这个
const toReactive = (value) => isObject(value) ? reactive(value) : value;// 是否为对象,如果是则调用reactive
class RefImpl {
// isShallow2是否浅层ref,咱们正常使用ref声明变量,这里默认false
constructor(value, isShallow2) {
this.dep = new Dep();
this["__v_isRef"] = true;
this["__v_isShallow"] = false;
this._rawValue = isShallow2 ? value : toRaw(value);
this._value = isShallow2 ? value : toReactive(value);//判断是否为浅层ref,否则调用toReactive
this["__v_isShallow"] = isShallow2;
}
get value() {
{
this.dep.track({//这里进行依赖收集
target: this,
type: "get",
key: "value"
});
}
return this._value;
}
set value(newValue) {
const oldValue = this._rawValue;
const useDirectValue = this["__v_isShallow"] || isShallow(newValue) || isReadonly(newValue);
newValue = useDirectValue ? newValue : toRaw(newValue);
if (hasChanged(newValue, oldValue)) {
this._rawValue = newValue;
this._value = useDirectValue ? newValue : toReactive(newValue);//修改ref对象的时候进行判断,是不是
{
this.dep.trigger({//这里是触发视图更新和逻辑更新
target: this,
type: "set",
key: "value",
newValue,
oldValue
});
}
}
}
}
到这里可以看出来,咱们在使用ref来声明变量的时候,如果是基本类型,则直接是通过RefImpl类里面的get和set语法糖对该value值进行相应的操作,获取和赋值
如果是复杂类型,toReactive函数则直接会走reactive函数
reactive
function reactive(target) {
if (isReadonly(target)) {
return target;
}
return createReactiveObject(
target,
false,
mutableHandlers,
mutableCollectionHandlers,
reactiveMap
);
}
function createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) {
// 源码中createReactiveObject还有其他判断,这里保留了最核心的部分
const targetType = getTargetType(target);
if (targetType === 0 /* INVALID */) {
return target;
}
// 创建一个响应式对象
const proxy = new Proxy(
target,
targetType === 2 /* COLLECTION */ ? collectionHandlers : baseHandlers
);
// 将 target 和 proxy 保存到 proxyMap 中
proxyMap.set(target, proxy);
// 返回 proxy
return proxy;
}
具体代码验证
const a = ref(1)
const b = ref({id:1})
console.log(isProxy(a));//false
console.log(isProxy(b));//false
console.log(isProxy(b.value));//true
console.log(isReactive(a));//false
console.log(isReactive(b));//false
console.log(isReactive(b.value));//true
通过这里可以看出来,ref声明的对象,底层都是通过reactive来实现的
结果
- ref
- 基本类型 ---> 使用RefImpl类的set和get方法实现数据更新
- 复杂类型 ---> 使用reactive对象实现双向绑定
- reactive ---> 使用proxy实现双向绑定