返回

从零打造响应式系统(三):深入剖析 Vue3 的 reactive 实现

前端

在上一篇文章中,我们实现了 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 的工作原理,以及如何使用它来构建自己的响应式应用。