vue双向实现
Vue 双向绑定的实现原理
Vue 的双向绑定主要通过 v-model 指令实现,底层结合了数据劫持(Object.defineProperty 或 Proxy)和发布-订阅模式。以下是核心实现机制:
数据劫持
Vue 2.x 使用 Object.defineProperty 劫持对象的属性访问和修改,Vue 3.x 改用 Proxy 实现更高效的数据监听。
Vue 2.x 示例:
const data = { text: '' };
Object.defineProperty(data, 'text', {
get() {
return this._text;
},
set(newVal) {
this._text = newVal;
console.log('数据更新了');
}
});
Vue 3.x 示例:

const data = { text: '' };
const proxy = new Proxy(data, {
get(target, key) {
return target[key];
},
set(target, key, value) {
target[key] = value;
console.log('数据更新了');
return true;
}
});
发布-订阅模式
通过 Dep(依赖收集器)和 Watcher(观察者)实现数据变化时的视图更新:
class Dep {
constructor() {
this.subscribers = [];
}
depend() {
if (Watcher.target) {
this.subscribers.push(Watcher.target);
}
}
notify() {
this.subscribers.forEach(sub => sub.update());
}
}
class Watcher {
constructor(vm, key, cb) {
this.vm = vm;
this.key = key;
this.cb = cb;
Watcher.target = this;
this.vm[this.key]; // 触发 getter 收集依赖
Watcher.target = null;
}
update() {
this.cb.call(this.vm, this.vm[this.key]);
}
}
v-model 的实现
v-model 是语法糖,本质上是 :value 和 @input 的组合:

<input v-model="text">
<!-- 等价于 -->
<input :value="text" @input="text = $event.target.value">
自定义双向绑定组件
通过 model 选项和 $emit 实现自定义组件的双向绑定:
子组件:
export default {
model: {
prop: 'value',
event: 'change'
},
props: ['value'],
methods: {
handleInput(e) {
this.$emit('change', e.target.value);
}
}
}
父组件使用:
<custom-input v-model="text"></custom-input>
注意事项
- Vue 2.x 中
Object.defineProperty无法检测数组下标变化,需通过Vue.set或数组方法触发更新。 - Vue 3.x 的
Proxy支持深层监听,但需注意性能开销。 - 复杂场景可结合
.sync修饰符或v-bind.sync实现多属性双向绑定。






