Vue2 通过 Object.defineProperty 对哪些数组进行了特殊处理?
在 Vue 2 中,为了实现对数组变化的监听,Vue 通过 Object.defineProperty 对数组进行了特殊处理。这种处理使得 Vue 能够检测到数组某些方法的调用,并相应地更新视图。
Vue 对数组进行了“包裹”(wrapping),修改了以下能够改变数组内容的方法,以便在它们被调用时触发视图更新:
push
pop
shift
unshift
splice
sort
reverse
这些方法被 Vue 重写,以便在调用它们时执行额外的逻辑来通知 Vue 组件数组已经发生变化,从而触发更新。
然而,
对于直接修改数组元素(例如通过索引赋值 array[index] = newValue)或者
修改数组的长度(例如 array.length = newLength),
Vue 默认是无法检测到的。要检测这些变化,
Vue 提供了一些替代方案,比如使用 Vue.set(this.$set) 方法或者使用 splice 方法来确保变化能够被检测到。
在 Vue 3 中,由于引入了 Composition API 和 Proxy 对象来替代 Vue 2 中的 Object.defineProperty,Vue 对响应式系统的实现方式有了根本性的变化。这种变化使得 Vue 3 能够更高效地追踪数据变化,并且在一定程度上解决了 Vue 2 中数组变更检测的一些限制。
在 Vue 3 中,当你使用响应式 API(如 reactive 或 ref)来创建响应式数组时,Vue 会使用 Proxy 对象来代理这个数组。这意味着,当你对这个数组进行操作时,Vue 能够拦截这些操作并相应地更新视图。
对于通过索引赋值 array[index] = newValue 的情况,Vue 3 能够检测到这种变化,因为 Proxy 代理了数组对象,并且拦截了对数组属性的写操作。所以,你不需要像 Vue 2 那样使用 Vue.set 或 this.$set 来确保变化能够被检测到。
同样地,对于修改数组长度的情况(如 array.length = newLength),Vue 3 也能检测到这种变化,因为 Proxy 同样拦截了对 length 属性的写操作。然而,需要注意的是,直接设置 length 属性可能会导致数组中未定义元素的产生,因为这些元素没有被 Vue 追踪为响应式的。因此,在大多数情况下,建议使用数组的方法(如 splice、push、pop 等)来修改数组长度,以确保所有元素都是响应式的。