实现vue双向绑定
Vue 双向绑定的实现原理
Vue 的双向绑定主要通过数据劫持结合发布者-订阅者模式实现,核心是 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)。
基于 Object.defineProperty 的实现(Vue 2.x)
数据劫持
通过 Object.defineProperty 劫持对象的属性,在属性被访问或修改时触发 getter 和 setter:
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log(`获取 ${key}: ${val}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`设置 ${key}: ${newVal}`);
val = newVal;
}
}
});
}
依赖收集 每个被劫持的属性会维护一个订阅者列表(Dep),在 getter 中收集依赖,在 setter 中通知更新:

class Dep {
constructor() {
this.subscribers = [];
}
depend() {
if (target && !this.subscribers.includes(target)) {
this.subscribers.push(target);
}
}
notify() {
this.subscribers.forEach(sub => sub());
}
}
观察者模式 通过 Watcher 监听数据变化并更新视图:
let target = null;
class Watcher {
constructor(func) {
target = func;
target();
target = null;
}
}
基于 Proxy 的实现(Vue 3.x)
Vue 3 使用 Proxy 替代 Object.defineProperty,能直接监听对象而非属性,并支持数组索引修改:

function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
track(target, key);
return target[key];
},
set(target, key, value) {
target[key] = value;
trigger(target, key);
return true;
}
});
}
模板编译
Vue 将模板编译为渲染函数,解析指令如 v-model:
v-model本质是:value绑定和@input事件的语法糖:<input v-model="message"> <!-- 等价于 --> <input :value="message" @input="message = $event.target.value">
实现简易双向绑定
完整示例代码:
// 数据劫持 + 发布订阅
class Dep {
constructor() { this.subs = new Set(); }
depend() { if (target) this.subs.add(target); }
notify() { this.subs.forEach(sub => sub()); }
}
function observe(obj) {
Object.keys(obj).forEach(key => {
let val = obj[key];
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
dep.depend();
return val;
},
set(newVal) {
val = newVal;
dep.notify();
}
});
});
}
let target = null;
function watch(fn) {
target = fn;
fn();
target = null;
}
// 使用示例
const data = { message: '' };
observe(data);
watch(() => {
document.getElementById('input').value = data.message;
document.getElementById('output').textContent = data.message;
});
document.getElementById('input').addEventListener('input', (e) => {
data.message = e.target.value;
});
对比 Vue 2 与 Vue 3 实现差异
- Vue 2:基于
Object.defineProperty,需递归遍历对象,无法检测数组索引变化。 - Vue 3:基于
Proxy,可监听整个对象,支持数组变化检测,性能更好。
通过以上机制,Vue 实现了数据变化自动更新视图、视图输入自动更新数据的双向绑定效果。






