vue双向实现
Vue 双向数据绑定的实现原理
Vue 的双向数据绑定主要通过 v-model 指令实现,其核心是结合了数据劫持(Object.defineProperty 或 Proxy)和发布-订阅模式。
数据劫持
Vue 2.x 使用 Object.defineProperty 监听对象属性的变化,Vue 3.x 改用 Proxy 实现更高效的数据劫持。当数据变化时,触发 setter 通知依赖更新。
// Vue 2.x 数据劫持示例
const data = { value: '' };
Object.defineProperty(data, 'value', {
get() {
return this._value;
},
set(newVal) {
this._value = newVal;
console.log('数据更新了');
}
});
模板编译
Vue 将模板编译为渲染函数,解析 v-model 指令时,会为元素绑定 input 事件(或其他表单事件),并动态更新数据属性。
<input v-model="message">
<!-- 编译后等效于 -->
<input :value="message" @input="message = $event.target.value">
发布-订阅模式
通过 Dep 和 Watcher 实现依赖收集和更新。每个数据属性有一个 Dep 实例,当渲染时触发 getter 收集依赖(Watcher),数据变化时通过 setter 通知 Watcher 更新视图。

自定义实现双向绑定
以下是一个简化版的实现示例:
数据监听
使用 Object.defineProperty 监听输入框的值变化。

function defineReactive(obj, key) {
let value = obj[key];
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
if (Dep.target) dep.addSub(Dep.target);
return value;
},
set(newVal) {
if (newVal === value) return;
value = newVal;
dep.notify();
}
});
}
依赖管理
实现 Dep 和 Watcher 类管理依赖关系。
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
class Watcher {
constructor(vm, exp, fn) {
this.vm = vm;
this.exp = exp;
this.fn = fn;
Dep.target = this;
vm[exp]; // 触发 getter 收集依赖
Dep.target = null;
}
update() {
this.fn(this.vm[this.exp]);
}
}
绑定指令
将输入框的 input 事件与数据属性关联。
function bindInput(input, vm, exp) {
input.addEventListener('input', e => {
vm[exp] = e.target.value;
});
new Watcher(vm, exp, value => {
input.value = value;
});
}
使用 Proxy 的实现(Vue 3 风格)
Vue 3 使用 Proxy 替代 Object.defineProperty,支持深层对象监听和数组变化。
function reactive(obj) {
const dep = new Dep();
return new Proxy(obj, {
get(target, key) {
if (Dep.target) dep.addSub(Dep.target);
return target[key];
},
set(target, key, value) {
if (target[key] === value) return true;
target[key] = value;
dep.notify();
return true;
}
});
}
总结
- 数据劫持:通过
Object.defineProperty或Proxy监听数据变化。 - 模板编译:将
v-model转换为:value和@input的语法糖。 - 依赖管理:利用
Dep和Watcher实现数据与视图的自动同步。
通过以上机制,Vue 实现了数据变化自动更新视图、视图输入自动更新数据的双向绑定效果。






