vue实现双向数据绑定的原理
Vue 双向数据绑定的原理
Vue 实现双向数据绑定的核心是通过 数据劫持 和 发布-订阅模式 结合实现的。主要依赖 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)来监听数据变化,并通过 v-model 指令实现视图与数据的双向绑定。
核心机制
数据劫持(响应式系统)
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 代理整个对象,能更好地支持动态新增属性和数组变化:

const proxy = new Proxy(obj, {
get(target, key) {
// 依赖收集
return Reflect.get(target, key);
},
set(target, key, value) {
// 触发更新
const result = Reflect.set(target, key, value);
dep.notify();
return result;
}
});
依赖收集与发布订阅
- Dep(依赖管理器):每个响应式属性关联一个 Dep 实例,用于存储依赖(Watcher)。
- Watcher(观察者):当数据变化时,Dep 会通知所有 Watcher 更新视图。
双向绑定的实现(v-model)
v-model 是语法糖,本质上是 :value 和 @input 的组合:
<input v-model="message">
<!-- 等价于 -->
<input :value="message" @input="message = $event.target.value">
具体流程
- 初始化阶段:Vue 遍历 data 对象,通过数据劫持监听所有属性。
- 模板编译:解析模板中的指令(如
v-model),创建对应的 Watcher。 - 依赖收集:渲染时触发 getter,将 Watcher 添加到当前属性的 Dep 中。
- 数据更新:当数据变化时,setter 触发 Dep 通知所有 Watcher 重新渲染视图。
与单向数据流的区别
Vue 的双向绑定实际上是单向数据流+事件监听的封装:
- 数据到视图:通过响应式系统自动更新。
- 视图到数据:通过事件(如
@input)手动更新数据。
注意事项
- Vue 2.x 中无法检测到对象属性的添加或删除,需使用
Vue.set/Vue.delete。 - 数组变异方法(如
push、pop)被重写以触发更新,但直接通过索引修改需用Vue.set。





