vue双向实现
Vue 双向数据绑定的实现原理
Vue 的双向数据绑定主要通过 v-model 指令实现,结合数据劫持(Object.defineProperty 或 Proxy)和发布-订阅模式完成。以下是核心实现方式:
基于 Object.defineProperty 的实现
-
数据劫持(响应式化)
通过Object.defineProperty监听对象属性的读取和修改:function defineReactive(obj, key, val) { const dep = new Dep(); // 依赖收集器 Object.defineProperty(obj, key, { get() { dep.depend(); // 收集当前依赖 return val; }, set(newVal) { if (newVal === val) return; val = newVal; dep.notify(); // 通知更新 } }); } -
依赖收集与触发
依赖管理器Dep和观察者Watcher实现订阅-发布:class Dep { constructor() { this.subscribers = []; } depend() { if (Dep.target) this.subscribers.push(Dep.target); } notify() { this.subscribers.forEach(watcher => watcher.update()); } } -
v-model的语法糖v-model本质是:value和@input的简写:<input v-model="message"> <!-- 等价于 --> <input :value="message" @input="message = $event.target.value">
基于 Proxy 的实现(Vue 3)
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); // 触发更新
return true;
}
});
}
自定义双向绑定实现示例
-
组件内实现
通过props和$emit实现父子组件双向绑定:Vue.component('CustomInput', { props: ['value'], template: ` <input :value="value" @input="$emit('input', $event.target.value)" > ` }); -
修饰符扩展
v-model支持修饰符(如.lazy、.number):<input v-model.lazy="message">
注意事项
- 性能影响:深层对象监听可能引发性能问题,建议扁平化数据结构。
- 数组限制:Vue 2 中直接通过索引修改数组需使用
Vue.set或数组方法(如push)。 - 兼容性:
Proxy无法在低版本浏览器中使用,Vue 3 需通过polyfill降级支持。
通过以上机制,Vue 实现了数据与视图的自动同步,开发者无需手动操作 DOM。







