vue实现双向绑定的是
Vue 实现双向绑定的原理
Vue 的双向绑定是通过数据劫持结合发布者-订阅者模式实现的,核心是 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)。以下是具体实现机制:
数据劫持(Data Observation)
在 Vue 2.x 中,通过 Object.defineProperty 劫持对象的属性,将其转化为 getter 和 setter。当数据被访问或修改时,可以触发相应的逻辑。
Object.defineProperty(obj, key, {
get() {
return value;
},
set(newVal) {
if (newVal !== value) {
value = newVal;
// 触发更新
}
}
});
在 Vue 3.x 中,改用 Proxy 实现更高效的数据劫持:
const proxy = new Proxy(obj, {
get(target, key) {
return target[key];
},
set(target, key, value) {
target[key] = value;
// 触发更新
}
});
依赖收集(Dependency Tracking)
在 getter 中,Vue 会收集当前属性的依赖(Watcher 实例)。每个组件实例对应一个 Watcher,负责监听数据变化并触发视图更新。

// 伪代码:依赖收集
class Dep {
constructor() {
this.subscribers = [];
}
depend() {
if (Watcher.target) {
this.subscribers.push(Watcher.target);
}
}
notify() {
this.subscribers.forEach(watcher => watcher.update());
}
}
模板编译(Template Compilation)
Vue 的模板会被编译为渲染函数(Render Function),渲染过程中会触发数据的 getter,从而完成依赖收集。例如:
<input v-model="message">
编译后的代码会生成类似以下逻辑:
// 伪代码:v-model 实现
input.addEventListener('input', (e) => {
this.message = e.target.value;
});
更新视图(View Update)
当数据变化时,setter 会通知依赖(Watcher)触发重新渲染(Re-render)。Vue 通过虚拟 DOM 对比(Diff)高效更新真实 DOM。

// 伪代码:Watcher 更新
class Watcher {
update() {
// 触发组件重新渲染
component.update();
}
}
双向绑定的核心:v-model
v-model 是语法糖,本质上是 :value 和 @input 的结合:
<input v-model="message">
<!-- 等价于 -->
<input :value="message" @input="message = $event.target.value">
对于自定义组件,v-model 默认使用 value prop 和 input 事件,但可以通过 model 选项配置:
// 自定义组件的 v-model
export default {
model: {
prop: 'checked',
event: 'change'
},
props: ['checked'],
methods: {
handleChange() {
this.$emit('change', newValue);
}
}
};
Vue 3.x 的优化
Vue 3.x 使用 Proxy 替代 Object.defineProperty,解决了以下问题:
- 直接监听对象而非属性,无需递归劫持。
- 支持数组索引和长度变化。
- 性能更高,尤其在大型对象上。
// Vue 3.x 的响应式实现
const reactive = (obj) => {
return new Proxy(obj, {
get(target, key) {
track(target, key); // 依赖收集
return target[key];
},
set(target, key, value) {
target[key] = value;
trigger(target, key); // 触发更新
}
});
};



