[vue3] ref 普通数据类型执行过程

本文涉及到的响应式类型判断可以参考 [vue3] isRef、isProxy、isReactive、isReadonly

我们在使用ref 定义变量时(const a = ref(null)), 首先会判断是不是 ref 类型,如果是直接返回,如果不是 返回 RefImpl 实例。我们每次定义的变量,如果是普通类型的值,那么直接返回这个值,如果是复杂类型,会通过 reactive 来转变为响应式数据。

  • 由于本文只是围绕 普通类型的值 展开讨论,可以直接认为 toRaw, toReactive 直接返回当前值就可以了

  • toReactive 实现,首先判断是不是 Object(value !==null && typeof value === ‘object’),如果是,执行reactive,否则直接返回

  • 后续章节在进行详细的介绍 toRaw、reactive

// core/packages/reactivity/src/ref.ts
export function ref(value?: unknown) {
  return createRef(value, false)
}
function createRef(rawValue: unknown, shallow: boolean) {
  if (isRef(rawValue)) {
    return rawValue
  }
  return new RefImpl(rawValue, shallow)
}
class RefImpl<T> {
  private _value: T
  private _rawValue: T

  public dep?: Dep = undefined
  public readonly __v_isRef = true

  constructor(value: T, public readonly __v_isShallow: boolean) {
    this._rawValue = __v_isShallow ? value : toRaw(value)
    this._value = __v_isShallow ? value : toReactive(value)
  }
	...
}
// core/packages/reactivity/src/reactive.ts
export const toReactive = <T extends unknown>(value: T): T =>
  isObject(value) ? reactive(value) : value

当我们执行 a.value 时会执行get 方法。

// core/packages/reactivity/src/ref.ts
class RefImpl<T> {
	....
  get value() {
    trackRefValue(this)
    return this._value
  }
	....
}

首先会跟踪ref 的value,跟踪副作用。然后返回当前 _value 的值。

export function trackRefValue(ref: RefBase<any>) {
  if (shouldTrack && activeEffect) {
    ref = toRaw(ref)
    if (__DEV__) {
      trackEffects(ref.dep || (ref.dep = createDep()), {
        target: ref,
        type: TrackOpTypes.GET,
        key: 'value'
      })
    } else {
      trackEffects(ref.dep || (ref.dep = createDep()))
    }
  }
}

当我们执行 a.value = 2,执行 set 操作。
首先判断新旧两个值是不是相同,如果不相同那么 _rawValue, _value 记录当前新的值。执行triggerRefValue

// core/packages/reactivity/src/ref.ts
class RefImpl<T> {
	...
  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.dep 此时为undifined我们目前可以认为 triggerRefValue 什么也没有干

export function triggerRefValue(ref: RefBase<any>, newVal?: any) {
  ref = toRaw(ref)
  const dep = ref.dep
  if (dep) {
    if (__DEV__) {
      triggerEffects(dep, {
        target: ref,
        type: TriggerOpTypes.SET,
        key: 'value',
        newValue: newVal
      })
    } else {
      triggerEffects(dep)
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值