回调函数中如果有读取了响应式数据的话则会触发 proxy 的 get 收集依赖,这时就能从 effectStack 上拿到该依赖对象了。
然后给 effect 增加了 computed lazy 属性后返回。
最后就是对外暴露的 effect 及 computed 函数了:
// 创建依赖对象并判断非计算属性则立即执行
function effect(fn, options = {}) {
let e = createReactiveEffect(fn, options)
if (!options.lazy) {
e()
}
return e
}// computed 内部调用 effect 并添加计算属性相关的 options
function computed(fn) {
const runner = effect(fn, {
computed: true,
lazy: true
})
return {
effect: runner,
get value() {
return runner()
}
}
}
computed 就不多说了,effect 就是将传入的回调函数传给 createReactiveEffect 创建依赖对象,然后执行依赖对象就会执行回调函数并收集该依赖对象。
总结
reactive 将传入的数据对象使用 proxy 包装,通过 proxy 的 get set 拦截数据的获取及修改,与 Vue2 的 defineProperty 一样,在 get 中收集依赖,在 set 中触发依赖;
effect 函数接受一个回调函数作为参数,将回调函数包装一下作为依赖对象后执行回调函数,回调函数执行时触发相关数据的 get 后进行依赖收集;

到此 Vue2 及 Vue3 中的数据响应式原理都分析完了。
Vue2 及 Vue3 数据响应式的对比
本次 Vue 对于数据响应式的升级主要在变化侦测部分。
Vue2 中的变化侦测实现对 Object 及 Array 分别进行了不同的处理,Objcet 使用了
Object.defineProperty API ,Array 使用了拦截器对 Array 原型上的能够改变数据的方法进行拦截。虽然也实现了数据的变化侦测,但存在很多局限 ,比如对象新增属性无法被侦测,以及通过数组下边修改数组内容,也因此在 Vue2 中经常会使用到 $set 这个方法对数据修改,以保证依赖更新。
Vue3 中使用了 es6 的 Proxy API 对数据代理,没有像 Vue2 中对原数据进行修改,只是加了代理包装,因此首先性能上会有所改善。其次解决了 Vue2 中变化侦测的局限性,可以不使用 $set 新增的对象属性及通过下标修改数组都能被侦测到。










