第四天-熟悉 Vue3 的响应式系统(ref)

131 阅读2分钟

ref

export function ref(value?: unknown) {
  return createRef(value, false)
}

function createRef(
  rawValue: unknown, 
  shallow: boolean  // 用于控制是否进行深层响应式处理 true:不进行,false:进行
  ) {
  // 判断 rawValue 是否为 ref 类型的对象
  if (isRef(rawValue)) {
    return rawValue
  }
  return new RefImpl(rawValue, shallow)
}

class RefImpl<T> {
  private _value: T // 对原始值的响应式处理
  private _rawValue: T  // 对原始值的引用

  public dep?: Dep = undefined  // dep 属性
  public readonly __v_isRef = true  // 标记,是否为 Ref 对象

  constructor(value: T, public readonly __v_isShallow: boolean) {
    this._rawValue = __v_isShallow ? value : toRaw(value)
    this._value = __v_isShallow ? value : toReactive(value)
  }

  get value() {
    // 收集依赖
    trackRefValue(this)
    return this._value
  }

  set value(newVal) {
    const useDirectValue =
      this.__v_isShallow || isShallow(newVal) || isReadonly(newVal)
    newVal = useDirectValue ? newVal : toRaw(newVal)
    if (hasChanged(newVal, this._rawValue)) {
      this._rawValue = newVal
      this._value = useDirectValue ? newVal : toReactive(newVal)
      triggerRefValue(this, newVal) // 触发更新以来
    }
  }
}

当你使用 ref 函数创建一个响应式引用时,Vue3 会调用 createRef 函数,并传入 valuefalse 作为参数,后者表示这是一个普通的 ref。

createRef 函数首先会判断 value 是否已经是一个 ref,如果是,则直接返回 value。否则,会创建一个新的 RefImpl 对象,并将 value 传入其中。

RefImpl 对象会包含 _value_rawValue 两个属性。在构造函数中,会根据 __v_isShallow 的值来判断是否要将传入的 value 变成响应式对象。

当你获取这个响应式引用的值时,Vue3 会调用 get 方法。在 get 方法中,首先会调用 trackRefValue 函数收集这个引用的依赖。

当你设置这个响应式引用的值时,Vue3 会调用 set 方法。在 set 方法中,会判断新值 newVal 是否与旧值 _rawValue 相等。如果不相等,则更新 _rawValue_value,并调用 triggerRefValue 函数触发这个引用的依赖。如果相等,则不进行更新。

今天我找到新工作上班了,所以更新速度可能会慢一点,内容可能会少一点,但绝对不会停下来的,今天就先看看 ref,后面看 reactive 如何对对象响应式处理