vue双向绑定原理实现
Vue 双向绑定原理实现
Vue 的双向绑定核心是通过数据劫持结合发布者-订阅者模式实现的,主要依赖 Object.defineProperty 或 Proxy(Vue 3)来监听数据变化,并通过事件机制通知视图更新。
数据劫持
通过 Object.defineProperty 或 Proxy 拦截对象的属性访问和修改,在属性被访问或修改时触发相应的逻辑。例如,使用 Object.defineProperty 实现数据劫持:

function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log(`读取属性 ${key}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`设置属性 ${key} 为 ${newVal}`);
val = newVal;
}
}
});
}
const data = {};
defineReactive(data, 'message', 'Hello');
data.message; // 触发 get
data.message = 'World'; // 触发 set
依赖收集与发布订阅
在数据劫持的基础上,需要实现依赖收集和发布订阅机制。当数据变化时,通知所有依赖该数据的订阅者更新视图。

class Dep {
constructor() {
this.subscribers = [];
}
depend() {
if (target && !this.subscribers.includes(target)) {
this.subscribers.push(target);
}
}
notify() {
this.subscribers.forEach(sub => sub());
}
}
let target = null;
function watchEffect(fn) {
target = fn;
fn();
target = null;
}
function defineReactive(obj, key, val) {
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
dep.depend();
return val;
},
set(newVal) {
if (newVal !== val) {
val = newVal;
dep.notify();
}
}
});
}
const data = {};
defineReactive(data, 'message', 'Hello');
watchEffect(() => {
console.log(`数据变化: ${data.message}`);
});
data.message = 'World'; // 触发更新
实现双向绑定
将数据劫持和发布订阅机制结合,实现输入框与数据的双向绑定:
<input id="input" type="text">
<div id="display"></div>
const input = document.getElementById('input');
const display = document.getElementById('display');
const data = {};
defineReactive(data, 'text', '');
watchEffect(() => {
display.textContent = data.text;
});
input.addEventListener('input', (e) => {
data.text = e.target.value;
});
Vue 3 的 Proxy 实现
Vue 3 使用 Proxy 替代 Object.defineProperty,可以更好地处理数组和动态新增属性:
function reactive(obj) {
const handlers = {
get(target, key, receiver) {
const result = Reflect.get(target, key, receiver);
track(target, key);
return result;
},
set(target, key, value, receiver) {
const oldValue = target[key];
const result = Reflect.set(target, key, value, receiver);
if (oldValue !== value) {
trigger(target, key);
}
return result;
}
};
return new Proxy(obj, handlers);
}
const data = reactive({ message: 'Hello' });
function track(target, key) {
// 依赖收集逻辑
}
function trigger(target, key) {
// 触发更新逻辑
}
总结
Vue 的双向绑定通过数据劫持监听数据变化,依赖收集和发布订阅机制实现视图与数据的同步。Vue 2 使用 Object.defineProperty,Vue 3 使用 Proxy 提升性能和功能支持。






