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">
适用于表单元素(如 input、textarea、select)。

自定义组件的双向绑定
在自定义组件中,需显式定义 model 选项并触发更新事件:
Vue.component('custom-input', {
props: ['value'],
model: {
prop: 'value',
event: 'update'
},
template: `
<input
:value="value"
@input="$emit('update', $event.target.value)"
>
`
});
使用时直接通过 v-model 绑定:

<custom-input v-model="message"></custom-input>
手动实现数据绑定(底层原理)
- 数据劫持
使用Object.defineProperty或Proxy监听数据变化:
const data = { message: '' };
Object.defineProperty(data, 'message', {
get() { return this._message; },
set(newVal) {
this._message = newVal;
console.log('数据更新:', newVal); // 触发视图更新
}
});
- 依赖收集与派发更新
Vue 通过Dep(依赖收集器)和Watcher(观察者)实现发布-订阅模式:
class Dep {
constructor() { this.subs = []; }
addSub(sub) { this.subs.push(sub); }
notify() { this.subs.forEach(sub => sub.update()); }
}
class Watcher {
update() { /* 更新视图 */ }
}
修饰符扩展功能
v-model 支持修饰符优化行为:
<input v-model.lazy="message"> <!-- 改为监听 change 事件 -->
<input v-model.number="age"> <!-- 自动转为数字 -->
<input v-model.trim="text"> <!-- 去除首尾空格 -->
对比单向数据流
双向绑定是单向数据流的语法糖,本质仍是:
- 数据 -> 视图(通过
:value绑定) - 视图 -> 数据(通过
@input事件)
注意事项
- 性能影响:深层对象监听需使用
Vue.set或展开运算符确保响应式。 - Proxy 替代:Vue 3 使用
Proxy替代Object.defineProperty,支持数组和对象深层监听。





