vue 数组响应式实现
Vue 数组响应式实现原理
Vue 通过重写数组的原型方法实现对数组变化的监听。核心思路是拦截数组的变异方法(如 push、pop、splice 等),在方法执行前后触发依赖更新。
重写数组原型
Vue 创建了一个继承自 Array.prototype 的对象作为新的数组原型,并重写了其中会修改原数组的方法:
const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto)
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
methodsToPatch.forEach(function (method) {
const original = arrayProto[method]
def(arrayMethods, method, function mutator (...args) {
const result = original.apply(this, args)
const ob = this.__ob__
let inserted
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if (inserted) ob.observeArray(inserted)
ob.dep.notify()
return result
})
})
响应式处理入口
在初始化数据时,Vue 会遍历对象属性,对数组进行特殊处理:

class Observer {
constructor(value) {
if (Array.isArray(value)) {
value.__proto__ = arrayMethods
this.observeArray(value)
} else {
this.walk(value)
}
}
observeArray(items) {
for (let i = 0, l = items.length; i < l; i++) {
observe(items[i])
}
}
}
处理新增元素
对于可能新增元素的方法(push、unshift、splice),需要对新元素进行响应式处理:
if (inserted) ob.observeArray(inserted)
触发更新
每个被观察的数组都有一个关联的 Dep 实例,当数组变化时通过 dep.notify() 通知所有订阅者:

ob.dep.notify()
注意事项
直接通过索引修改数组元素或修改数组长度不会被检测到:
vm.items[index] = newValue // 非响应式
vm.items.length = newLength // 非响应式
应使用 Vue.set 或数组的变异方法:
Vue.set(vm.items, index, newValue)
vm.items.splice(index, 1, newValue)
总结
Vue 的数组响应式实现通过以下方式工作:
- 创建继承自原生数组原型的变异版本
- 重写会修改数组的7个方法
- 方法执行后对新元素进行响应式处理
- 通过依赖收集和通知机制触发视图更新
- 提供
Vue.set和变异方法作为修改数组的安全方式






