解读vue3源码(2)——reactive、ref

文章详细解读了Vue3的reactive函数和ref函数的底层实现,包括reactive如何创建响应式对象,通过createReactiveObject、reactiveHandlers、get和set等函数实现数据的双向绑定。同时,ref函数通过createRef创建响应式数据对象,利用getter/setter进行值的获取和设置,并通过track和trigger处理依赖收集与更新。
摘要由CSDN通过智能技术生成
Vue3的reactive底层源码是Vue3响应式系统的核心部分,它实现了数据的双向绑定,
使得数据的变化能够自动更新视图。下面是对Vue3的reactive底层源码的详细解读:

1. reactive函数

reactive函数是Vue3响应式系统的入口函数,它接收一个普通的JavaScript对象作为参数,
返回一个响应式的Proxy对象。在reactive函数内部,会调用createReactiveObject函数来创建响应式对象。

2. createReactiveObject函数

createReactiveObject函数用来创建响应式对象,它接收三个参数:target、isReadonly和baseHandlers。
其中,target是要转换成响应式对象的普通JavaScript对象,isReadonly表示是否为只读对象,
baseHandlers是处理对象属性的基本处理器。

在createReactiveObject函数内部,会判断target是否已经被转换成响应式对象,
如果已经转换,则直接返回该对象。否则,会创建一个响应式对象,并将其缓存到WeakMap中,以便下次使用时直接返回缓存的对象。

3. reactiveHandlers

reactiveHandlers是处理响应式对象属性的处理器,它继承了baseHandlers,
并在其基础上增加了一些处理逻辑。在reactiveHandlers中,主要是对属性的读取和修改进行了拦截,并在拦截器中进行了相应的处理。

4. get函数

get函数是reactiveHandlers中的一个拦截器,用来拦截对响应式对象属性的读取操作。
在get函数中,会先调用baseGet函数获取属性的值,然后判断该值是否为对象,
如果是对象,则递归调用reactive函数将其转换为响应式对象,并返回该响应式对象。如果不是对象,则直接返回该值。

5. set函数

set函数是reactiveHandlers中的一个拦截器,用来拦截对响应式对象属性的修改操作。
在set函数中,会先调用baseSet函数设置属性的值,然后判断该属性是否为新添加的属性,
如果是,则调用trigger函数触发依赖更新。如果不是新添加的属性,则判断新值和旧值是否相等,如果不相等,则调用trigger函数触发依赖更新。

6. trigger函数

trigger函数用来触发依赖更新,它接收两个参数:target和key。其中,target是被修改的响应式对象,
key是被修改的属性名。在trigger函数内部,会先判断该响应式对象是否有依赖,如果没有,
则直接返回。否则,会遍历依赖列表,依次调用每个依赖的更新函数。

7. effect函数

effect函数用来创建一个响应式副作用函数,它接收一个函数作为参数,并返回一个响应式副作用函数。
在effect函数内部,会先调用传入的函数获取初始值,并将该函数保存到activeEffect变量中。
然后,会调用该函数,并在调用过程中对响应式对象进行读取操作,以便收集依赖。最后,会将activeEffect变量清空,并返回响应式副作用函数。

8. track函数

track函数用来收集依赖,它接收两个参数:target和key。其中,target是被读取的响应式对象,
key是被读取的属性名。在track函数内部,会先判断是否有activeEffect变量,如果有,则将该变量保存到依赖列表中。

9. reactive和effect的使用

使用reactive函数将普通JavaScript对象转换为响应式对象后,就可以使用effect函数创建响应式副作用函数了。
在响应式副作用函数中,对响应式对象进行读取操作时,会自动收集依赖,并在响应式对象发生变化时自动更新视图。

以上就是对Vue3的reactive底层源码的详细解读。
Vue3 的 `ref` 是一个函数,用于创建一个响应式的数据对象。它的底层源码实现涉及到了 Vue3 的响应式系统和 Proxy 对象。

下面是 `ref` 的底层源码实现:


function ref(value) {
  return createRef(value)
}

function createRef(rawValue) {
  const r = {
    __v_isRef: true,
    get value() {
      track(r, TrackOpTypes.GET, 'value')
      return rawValue
    },
    set value(newVal) {
      if (hasChanged(newVal, rawValue)) {
        rawValue = newVal
        trigger(r, TriggerOpTypes.SET, 'value', newVal)
      }
    }
  }
  return r
}


`ref` 函数实际上是调用了 `createRef` 函数,并将传入的值作为参数传递给 `createRef` 函数。

`createRef` 函数返回一个对象,该对象包含一个 `value` 属性和一个 `__v_isRef` 属性。
`value` 属性是一个 getter/setter 函数,用于获取和设置响应式数据的值。
`__v_isRef` 属性用于标识该对象是一个响应式数据对象。

在 `get` 函数中,我们调用了 `track` 函数,用于收集依赖。
`track` 函数会将当前的响应式数据对象和操作类型(`TrackOpTypes.GET`)传递给响应式系统的 `track` 函数,用于收集依赖。

在 `set` 函数中,我们首先判断新值是否与旧值相等,如果不相等,则更新 `rawValue` 的值,
并调用 `trigger` 函数,用于触发更新。
`trigger` 函数会将当前的响应式数据对象、操作类型(`TriggerOpTypes.SET`)、
属性名(`value`)和新值传递给响应式系统的 `trigger` 函数,用于触发更新。

总结一下,`ref` 函数的底层源码实现主要涉及到了以下几个方面:

1. 创建一个响应式数据对象,该对象包含一个 `value` 属性和一个 `__v_isRef` 属性。
2. 在 `get` 函数中,调用 `track` 函数,用于收集依赖。
3. 在 `set` 函数中,更新 `rawValue` 的值,并调用 `trigger` 函数,用于触发更新。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值