• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

[Vue 源码] Vue 3.2 - Ref 原理

武飞扬头像
书笙
帮助79

运行结果

代码示例

  <script src="./dist/reactivity.global.js"></script>
  <body>
    <div id="app"></div>
    <script>
      let { ref, effect } = VueReactivity
      let state = ref(false)

      effect(() => {
        app.innerHTML = `ref is ${state.value} `
      })

      setTimeout(() => {
        state.value = true
      }, 2000)
    </script>

执行第一句代码:ref(false), 调用 ref 函数 第一: ref函数,调用 createRef 函数。

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

第二:createRef 函数中, 通过 new RefImpl 实例化 ref对象。

function createRef(rawValue: unknown, shallow: boolean) {
  if (isRef(rawValue)) {
    return rawValue
  }
  return new RefImpl(rawValue, shallow)
}

第三:调用 RefImpl 的 constructor 构造函数。构造函数中初始化 ref 实例对象的 _value 和 _rawValue, 本例中是将 false 传给 toRective, 如果 value 是一个对象则将 通过 reactive 函数包装成 响应式对象,本例中直接返回 false。

第四:返回创建好的 ref 对象。

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

第四:开始执行第二句代码 effect(() => { app.innerHTML = `ref is ${state.value} ` }) , effect 函数调用创建 ReactiveEffect 对象,将 activeEffect 对象置为当前的 ReactiveEffect 对象。调用 run 方法,调用 () => { app.innerHTML = `ref is ${state.value}` } 函数

第五:在该函数中触发 state 响应式 ref 对象 value 属性的 getter 操作。

  • 通过 trackRefValue 函数 收集依赖到 ref.deps 当中。 {dep: [ReactiveEffect]}

  • 返回_value 值,也就是 false

  get value() {
    trackRefValue(this)
    return this._value
  }
  • app.innerHTML = -_value.

初始渲染完成。

更新阶段

执行第一句代码: setTimeout(() => { state.value = true }, 2000)

触发 响应式对象 ref 的 value 属性的 setter 操作。

  • 修改 _value 为新值
this._rawValue = newVal
this._value = useDirectValue ? newVal : toReactive(newVal)
  • triggerRefValue 来触发依赖列表
  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)
   }
 }
  • triggerRefValue 函数中 触发一系列 trigger 操作,我们再前面的文章多次聊到过。这里直接执行 ref 对象依赖列表 dep属性 中 ReactiveEffec 对象的 run 方法。也就是 () => { app.innerHTML = ref is ${state.value} }

  • 再次通过 state.value 触发 ref 对象 value 属性的 getter 操作,返回最新值,渲染,然后再次追踪依赖。

  • 等待下一次的更新。

自此更新完毕。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanffhgg
系列文章
更多 icon
同类精品
更多 icon
继续加载