vue双向实现原理
Vue 双向数据绑定的实现原理
Vue 的双向数据绑定主要通过数据劫持结合发布-订阅模式实现,核心是 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)。
数据劫持
Vue 2.x 使用 Object.defineProperty 劫持对象的属性访问和修改。通过定义属性的 getter 和 setter,在数据变化时触发更新。
let data = { name: 'Vue' };
Object.defineProperty(data, 'name', {
get() {
console.log('获取数据');
return val;
},
set(newVal) {
console.log('设置数据');
val = newVal;
// 触发更新
}
});
Vue 3.x 改用 Proxy,可以直接监听整个对象而非属性,解决了 Vue 2.x 中无法监听新增属性的问题。
let data = { name: 'Vue' };
let proxy = new Proxy(data, {
get(target, key) {
console.log('获取数据');
return target[key];
},
set(target, key, value) {
console.log('设置数据');
target[key] = value;
// 触发更新
return true;
}
});
依赖收集与发布-订阅
每个响应式数据会维护一个依赖列表(Dep),用于存储所有依赖该数据的 Watcher 实例。当数据变化时,Dep 会通知所有 Watcher 更新视图。
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
class Watcher {
update() {
// 更新视图
}
}
模板编译
Vue 的模板编译器将模板转换为渲染函数。在编译过程中,解析指令(如 v-model)并生成对应的数据绑定代码。
对于 v-model,它本质上是语法糖,结合了 :value 绑定和 @input 事件监听。
<input v-model="message">
<!-- 等价于 -->
<input :value="message" @input="message = $event.target.value">
整体流程
- 初始化时,通过数据劫持监听数据变化。
- 编译模板时,为每个绑定创建 Watcher 并添加到对应数据的 Dep 中。
- 数据变化时,触发 setter,Dep 通知所有 Watcher 更新视图。
- 用户输入触发事件,更新数据,形成双向绑定循环。
Vue 3.x 的改进在于使用 Proxy 提高了响应式系统的性能和灵活性,同时引入了 Composition API 增强代码组织能力。







