vue双向绑定实现面试
Vue 双向绑定的实现原理
Vue 的双向绑定主要通过数据劫持结合发布-订阅模式实现,核心是 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)。
数据劫持(Vue 2.x)
通过 Object.defineProperty 劫持对象的属性,在属性被访问或修改时触发 getter 和 setter:

function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log(`get ${key}: ${val}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`set ${key}: ${newVal}`);
val = newVal;
}
}
});
}
依赖收集与发布-订阅
每个响应式属性有一个 Dep(依赖收集器),用于存储依赖(Watcher)。当数据变化时,通知所有 Watcher 更新视图:
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
class Watcher {
update() {
console.log('视图更新');
}
}
双向绑定实现示例
结合 v-model 指令,实现输入框与数据的双向绑定:

<input v-model="message" />
<p>{{ message }}</p>
底层逻辑是 v-model 语法糖,等价于:
<input
:value="message"
@input="message = $event.target.value"
/>
Vue 3.x 的 Proxy 实现
Vue 3 使用 Proxy 替代 Object.defineProperty,解决了深层对象监听和数组变化检测的问题:
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
track(target, key);
return Reflect.get(target, key);
},
set(target, key, value) {
Reflect.set(target, key, value);
trigger(target, key);
}
});
}
常见面试问题
1. Vue 2.x 双向绑定的局限性
- 无法检测对象属性的添加或删除(需用
Vue.set/Vue.delete)。 - 数组的索引修改或长度变化无法触发更新(需用变异方法如
push)。
2. Vue 3 为何改用 Proxy
- 直接监听整个对象而非属性,支持动态新增属性。
- 性能更好,无需递归遍历对象。
3. 虚拟 DOM 的作用
- 通过 diff 算法最小化 DOM 操作,提升性能。
- 将数据变化批量更新到真实 DOM。
4. 实现简易双向绑定
// 简易版
const data = { text: '' };
const input = document.querySelector('input');
const span = document.querySelector('span');
Object.defineProperty(data, 'text', {
set(value) {
input.value = value;
span.textContent = value;
}
});
input.addEventListener('input', (e) => {
data.text = e.target.value;
});






