vue双向绑定实现方式
Vue 双向绑定的实现方式
Vue 的双向绑定主要通过 v-model 指令实现,其核心原理是结合数据劫持(Object.defineProperty 或 Proxy)和发布-订阅模式。以下是具体实现方式:
使用 v-model 指令
v-model 是语法糖,默认绑定 value 属性并监听 input 事件。例如在输入框中:
<input v-model="message">
等价于:
<input :value="message" @input="message = $event.target.value">
数据劫持
Vue 2.x 使用 Object.defineProperty 劫持数据属性的 getter 和 setter,实现数据变动时触发更新:
Object.defineProperty(obj, key, {
get() { return val; },
set(newVal) {
val = newVal;
dep.notify(); // 通知依赖更新
}
});
Vue 3.x 改用 Proxy 代理整个对象,支持深层监听和数组变动:
const proxy = new Proxy(obj, {
get(target, key) { return Reflect.get(target, key); },
set(target, key, value) {
Reflect.set(target, key, value);
triggerUpdate(); // 触发更新
return true;
}
});
发布-订阅模式
每个响应式属性关联一个 Dep(依赖收集器),在 getter 中收集依赖(Watcher),在 setter 中通知依赖更新:
class Dep {
constructor() { this.subs = []; }
addSub(sub) { this.subs.push(sub); }
notify() { this.subs.forEach(sub => sub.update()); }
}
自定义组件实现双向绑定
在自定义组件中,v-model 默认绑定 modelValue 并触发 update:modelValue 事件:
<CustomComponent v-model="message" />
组件内部需显式处理:
props: ['modelValue'],
emits: ['update:modelValue'],
template: `
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
>
`
多值双向绑定
Vue 3.x 支持多个 v-model 绑定,如:
<UserName
v-model:first-name="firstName"
v-model:last-name="lastName"
/>
组件内部对应 firstName 和 update:firstName 事件。
修饰符
v-model 支持修饰符,例如:
.lazy:将input事件改为change事件。.number:自动将输入转为数字。.trim:自动去除首尾空格。
通过以上机制,Vue 实现了高效的双向数据绑定,简化了表单和组件间的数据同步。







