ref源码解析

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实现双向绑定
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容