vue数据监听具体实现
Vue 数据监听实现原理
Vue 的数据监听主要通过 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)实现,核心是依赖收集和派发更新。
Vue 2.x 基于 Object.defineProperty
-
初始化数据监听 遍历数据对象的属性,通过
Object.defineProperty将属性转换为 getter/setter:
function defineReactive(obj, key, val) { Object.defineProperty(obj, key, { enumerable: true, configurable: true, get() { console.log('收集依赖'); return val; }, set(newVal) { if (newVal === val) return; console.log('触发更新'); val = newVal; } }); } -
依赖收集 在 getter 中,通过
Dep类和Watcher类建立依赖关系:class Dep { constructor() { this.subs = []; } addSub(sub) { this.subs.push(sub); } notify() { this.subs.forEach(sub => sub.update()); } } -
数组监听 对数组方法(如
push、pop)进行重写,在调用原生方法后手动触发更新:
const arrayProto = Array.prototype; const arrayMethods = Object.create(arrayProto); ['push', 'pop'].forEach(method => { const original = arrayProto[method]; arrayMethods[method] = function(...args) { const result = original.apply(this, args); dep.notify(); // 触发更新 return result; }; });
Vue 3.x 基于 Proxy
-
Proxy 代理 使用
Proxy直接监听整个对象,无需递归遍历属性:function reactive(obj) { return new Proxy(obj, { get(target, key) { track(target, key); // 依赖收集 return Reflect.get(target, key); }, set(target, key, value) { Reflect.set(target, key, value); trigger(target, key); // 触发更新 return true; } }); } -
性能优化 Proxy 能直接监听新增/删除属性,且对嵌套对象延迟处理(惰性监听)。
差异对比
- Vue 2.x:需递归遍历对象、需特殊处理数组,无法检测新增属性(需
Vue.set)。 - Vue 3.x:支持动态属性、性能更高,但需注意浏览器兼容性(IE 不支持 Proxy)。
实际应用建议
- 对于复杂对象,优先使用 Vue 3.x 的
reactive或ref。 - 在 Vue 2.x 中修改数组时,使用
Vue.set或数组的变异方法(如splice)。






