vue 双向实现原理
Vue 双向绑定的实现原理
Vue 的双向绑定主要通过数据劫持结合发布-订阅模式实现,核心是 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)。
数据劫持
通过 Object.defineProperty 或 Proxy 拦截对象的属性读写操作,在属性被访问或修改时触发相应的逻辑。
// Vue 2.x 使用 Object.defineProperty
const data = { value: '' };
Object.defineProperty(data, 'value', {
get() {
return this._value;
},
set(newValue) {
this._value = newValue;
// 触发更新
}
});
依赖收集
每个响应式属性都有一个依赖列表(Dep),用于存储所有依赖于该属性的 Watcher 实例。当属性被访问时,当前 Watcher 会被添加到依赖列表中。
class Dep {
constructor() {
this.subscribers = [];
}
depend() {
if (target) {
this.subscribers.push(target);
}
}
notify() {
this.subscribers.forEach(sub => sub());
}
}
发布-订阅模式
当数据变化时,Dep 会通知所有 Watcher 执行更新操作。Watcher 负责将新数据渲染到视图或更新模型。
function watcher(fn) {
target = fn;
fn();
target = null;
}
双向绑定实现
通过 v-model 指令将表单元素的值与 Vue 实例的数据绑定。表单输入时触发 input 事件更新数据,数据变化时通过响应式系统更新视图。
// 简化版 v-model 实现
<input v-model="message" />
// 等价于
<input :value="message" @input="message = $event.target.value" />
Vue 3 的改进
Vue 3 使用 Proxy 替代 Object.defineProperty,解决了以下问题:

- 无法检测到对象属性的添加或删除。
- 对数组的索引修改和长度变化无法监听。
Proxy可以直接监听整个对象,无需递归遍历属性。
// Vue 3 使用 Proxy
const data = new Proxy({ value: '' }, {
get(target, key) {
return target[key];
},
set(target, key, value) {
target[key] = value;
// 触发更新
return true;
}
});
总结
Vue 的双向绑定通过数据劫持、依赖收集和发布-订阅模式实现,v-model 是语法糖,底层通过事件监听和属性绑定完成。Vue 3 的 Proxy 提供了更强大的响应式能力。






