1. Vue 2 数组响应式原理深度解析
在 Vue 2 的响应式系统中,Object.defineProperty 是核心实现机制。对于普通对象属性,Vue 通过 getter/setter 拦截属性访问和修改。但当处理数组时,这套机制存在天然缺陷——数组的变异方法(如 push/pop)不会触发属性 setter,而直接索引赋值(arr[0]=1)和 length 修改也无法被捕获。为此 Vue 2 采用了"方法劫持"的解决方案。
1.1 被重写的数组方法清单
Vue 2 对以下 7 个会改变原数组的方法进行了包装处理:
- push() - 末尾添加元素
- pop() - 移除末尾元素
- shift() - 移除首元素
- unshift() - 首部添加元素
- splice() - 增删改多功能方法
- sort() - 数组排序
- reverse() - 数组反转
这些方法被重写的核心逻辑是:
javascript复制const originalMethods = Array.prototype
const arrayMethods = Object.create(originalMethods)
['push','pop','shift','unshift','splice','sort','reverse'].forEach(method => {
const original = originalMethods[method]
def(arrayMethods, method, function mutator(...args) {
const result = original.apply(this, args)
const ob = this.__ob__
ob.dep.notify() // 关键:触发依赖通知
return result
})
})
1.2 方法劫持的实现细节
当通过 new Vue() 或 Vue.observable() 创建响应式数组时,Vue 会:
- 将该数组的原型(
__proto__)指向重写后的arrayMethods
