vue 双向实现原理
Vue 双向绑定的实现原理
Vue 的双向绑定主要通过数据劫持结合发布-订阅模式实现,核心是 v-model 指令和响应式系统。
数据劫持与响应式
Vue 使用 Object.defineProperty(Vue 2)或 Proxy(Vue 3)劫持数据对象的属性,在属性被访问或修改时触发 getter/setter。例如:
// Vue 2 的简化实现
function defineReactive(obj, key) {
let value = obj[key];
Object.defineProperty(obj, key, {
get() {
console.log('读取数据');
return value;
},
set(newVal) {
if (newVal !== value) {
console.log('更新数据');
value = newVal;
// 通知依赖更新
}
}
});
}
依赖收集与发布订阅
每个响应式属性关联一个 Dep(依赖管理器),用于收集依赖该属性的 Watcher(订阅者)。当数据变化时,Dep 通知所有 Watcher 更新视图。
class Dep {
constructor() {
this.subscribers = [];
}
depend() {
if (target && !this.subscribers.includes(target)) {
this.subscribers.push(target);
}
}
notify() {
this.subscribers.forEach(sub => sub());
}
}
v-model 的实现
v-model 是语法糖,本质上是 value 属性绑定和 input 事件监听的组合。例如:
<input v-model="message">
<!-- 等价于 -->
<input :value="message" @input="message = $event.target.value">
虚拟 DOM 与更新优化
数据变化后触发重新渲染,Vue 通过虚拟 DOM 的 diff 算法高效更新真实 DOM,减少性能开销。
双向绑定的关键点
- 数据驱动视图:数据变化自动更新 DOM。
- 视图影响数据:通过事件监听(如
input)修改数据。 - 异步更新队列:Vue 将多次数据变更合并为一次视图更新,提高性能。
Vue 3 的改进
Vue 3 使用 Proxy 替代 Object.defineProperty,解决了无法监听新增属性和数组变化的问题,并提高了性能。例如:
const proxy = new Proxy(obj, {
get(target, key) {
track(target, key); // 依赖收集
return target[key];
},
set(target, key, value) {
target[key] = value;
trigger(target, key); // 触发更新
}
});






