vue实现双向绑定的是
Vue 双向绑定的实现原理
Vue 实现双向绑定的核心机制是通过数据劫持结合发布者-订阅者模式,利用 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)来监听数据变化,并通过指令和事件绑定实现视图与数据的同步更新。
核心机制
数据劫持与响应式系统
Vue 通过劫持数据的 getter 和 setter 实现响应式:
-
Vue 2.x:使用
Object.defineProperty递归遍历对象的属性,将其转换为getter/setter。Object.defineProperty(obj, key, { get() { return value; }, set(newVal) { if (newVal !== value) { value = newVal; dep.notify(); // 通知订阅者更新 } } }); -
Vue 3.x:改用
Proxy代理整个对象,避免递归性能问题,并支持动态新增属性。new Proxy(obj, { get(target, key) { return Reflect.get(target, key); }, set(target, key, value) { Reflect.set(target, key, value); triggerUpdate(); // 触发更新 } });
依赖收集与派发更新
- Dep(依赖管理器):每个响应式属性关联一个
Dep实例,用于收集依赖(Watcher)。 - Watcher(订阅者):在组件渲染时创建,负责更新视图。当数据变化时,
Dep通知所有Watcher执行更新。
双向绑定的具体实现
v-model 指令v-model 是语法糖,本质是 :value 绑定和 @input 事件的组合:
-
表单元素(如
<input>):<input v-model="message"> <!-- 等价于 --> <input :value="message" @input="message = $event.target.value"> -
自定义组件:
需显式定义model选项或通过props/emit:export default { props: ['value'], methods: { updateValue(newVal) { this.$emit('input', newVal); } } };
关键代码示例
Vue 2.x 响应式实现片段
class Dep {
constructor() { this.subs = []; }
addSub(sub) { this.subs.push(sub); }
notify() { this.subs.forEach(sub => sub.update()); }
}
function observe(data) {
Object.keys(data).forEach(key => {
let value = data[key];
const dep = new Dep();
Object.defineProperty(data, key, {
get() {
if (Dep.target) dep.addSub(Dep.target);
return value;
},
set(newVal) {
if (newVal !== value) {
value = newVal;
dep.notify();
}
}
});
});
}
总结
- 数据驱动视图:通过响应式系统自动更新 DOM。
- 视图反馈数据:通过事件监听(如
@input)修改数据。 - 升级优化:Vue 3 的
Proxy解决了 Vue 2 中无法检测数组/对象新增属性的限制。







