从零打造响应式系统(三):深入剖析 Vue3 的 reactive 实现
2023-11-18 21:08:52
在上一篇文章中,我们实现了 reactive 方法,它内部采用了 Proxy 来实现对象属性操作的拦截。这是实现响应式系统的前提,我们必须先拦截到用户对属性的访问,之后才能做依赖收集;再拦截到用户对属性的修改,最后更新视图。
依赖收集与视图更新
在 Vue3 中,依赖收集和视图更新主要通过 effect 函数实现。effect 函数接收一个回调函数作为参数,当该回调函数被调用时,effect 函数会自动收集回调函数中访问过的所有响应式对象和它们的属性。当这些响应式对象或属性发生变化时,effect 函数会重新执行回调函数,从而更新视图。
为了实现依赖收集,effect 函数内部使用了 track 和 trigger 函数。track 函数用于收集依赖,它会将当前正在执行的 effect 函数与正在访问的响应式对象和属性关联起来。trigger 函数用于触发依赖,它会在响应式对象或属性发生变化时,通知所有与该对象或属性相关联的 effect 函数,让它们重新执行回调函数。
reactive 的实现
reactive 函数的实现非常简单,它只需要创建一个 Proxy 对象,并返回该 Proxy 对象。Proxy 对象的构造函数接收两个参数,第一个参数是目标对象,第二个参数是处理程序对象。处理程序对象定义了当目标对象发生变化时,应该执行哪些操作。
在 Vue3 中,处理程序对象包含了 track 和 trigger 两个方法。track 方法用于收集依赖,trigger 方法用于触发依赖。当用户访问目标对象或修改目标对象的属性时,Proxy 对象会自动调用 track 或 trigger 方法,从而实现依赖收集和视图更新。
响应式系统示例
下面是一个简单的响应式系统示例,它使用 Vue3 的 reactive 函数和 effect 函数实现了响应式数据绑定:
const app = Vue.createApp({
data() {
return {
count: 0
}
},
template: `
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
`,
methods: {
increment() {
this.count++
}
}
})
app.mount('#app')
在这个示例中,我们使用 reactive 函数创建了一个响应式对象 data,并将其作为 Vue 组件的 data 属性。然后,我们使用 effect 函数收集对 data.count 属性的访问,并将其更新到视图中。当用户点击按钮时,increment 方法会将 data.count 的值加一,这将触发 effect 函数重新执行回调函数,从而更新视图中的计数。
总结
在本文中,我们深入剖析了 Vue3 中 reactive 的实现,它利用 Proxy 实现属性访问拦截,借助 effect、track 和 trigger 函数实现依赖收集和视图更新,从而打造出高效的响应式系统。您了解了 reactive 的工作原理,以及如何使用它来构建自己的响应式应用。