返回

深入解析 Vue.js 数据响应式原理(三)—— 数组依赖收集与更新

前端

Vue.js 数据响应式原理(二)中,我们已经实现了对象类型的依赖收集和依赖更新。本节内容将继续数据的依赖收集和依赖更新,但重点放在数组类型上。

对于一个对象,我们给每一个对象的属性定义了一个dep。而对于数组,则是给整个数组定义了一个dep。只要触发了这个数组的那七个方法,就会触发数据更新。

const methodsToPatch = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
]

methodsToPatch.forEach(method => {
  const original = Array.prototype[method]
  Object.defineProperty(Array.prototype, method, {
    value: function (...args) {
      const result = original.apply(this, args)
      // 数组变异方法触发后,会执行dep.notify()通知所有订阅者更新
      dep.target.addDep(dep)
      return result
    },
    configurable: true,
    enumerable: false,
    writable: true
  })
})

上面的代码表示,只要触发了数组的这七个方法,就会触发数据更新。

数组的依赖收集和依赖更新与对象的依赖收集和依赖更新基本一致,不同之处在于数组的依赖收集是针对整个数组进行的,而对象的依赖收集是针对每一个属性进行的。

数组的依赖收集

数组的依赖收集是在数组的方法中进行的。当数组的方法被调用时,就会触发依赖收集。依赖收集的过程如下:

  1. 获取当前正在执行的 Watcher 对象。
  2. 将 Watcher 对象添加到数组的dep中。

数组的依赖更新

数组的依赖更新是在数组的方法执行完毕后进行的。依赖更新的过程如下:

  1. 获取数组的dep
  2. 调用depnotify()方法,通知所有订阅者更新。

对象与数组在依赖收集和依赖更新方面的异同

对象与数组在依赖收集和依赖更新方面的异同如下:

  • 相同点:
    • 对象和数组的依赖收集都是在对象或数组的方法中进行的。
    • 对象和数组的依赖更新都是在对象或数组的方法执行完毕后进行的。
  • 不同点:
    • 对象的依赖收集是针对每一个属性进行的,而数组的依赖收集是针对整个数组进行的。
    • 对象的依赖更新是针对每一个属性进行的,而数组的依赖更新是针对整个数组进行的。

总结

本文详细解析了 Vue.js 中数组的依赖收集和依赖更新机制,深入剖析了数组变异方法(如 push、pop、shift、unshift、splice、sort 和 reverse)如何触发数据的响应式更新。同时,还对比了对象与数组在依赖收集和依赖更新方面的异同,帮助读者全面理解 Vue.js 的数据响应式原理。