vue实现mvvm
Vue 的 MVVM 实现原理
Vue 通过数据劫持和发布-订阅模式实现 MVVM(Model-View-ViewModel)架构。核心在于数据绑定和响应式系统。
数据劫持(响应式系统)
Vue 使用 Object.defineProperty(Vue 2)或 Proxy(Vue 3)劫持数据对象的属性,监听数据变化。当数据被修改时,触发视图更新。
Vue 2 实现示例:
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
return val;
},
set(newVal) {
if (newVal === val) return;
val = newVal;
// 触发更新
dep.notify();
}
});
}
Vue 3 实现示例:
const reactive = (target) => {
return new Proxy(target, {
get(target, key) {
return Reflect.get(target, key);
},
set(target, key, value) {
Reflect.set(target, key, value);
// 触发更新
trigger(target, key);
return true;
}
});
};
依赖收集(发布-订阅模式)
每个响应式属性有一个依赖收集器(Dep),用于存储依赖该属性的 Watcher(订阅者)。当数据变化时,Dep 通知所有 Watcher 更新视图。
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
class Watcher {
update() {
// 更新视图
patch();
}
}
模板编译
Vue 将模板编译为渲染函数,生成虚拟 DOM(VNode)。通过对比新旧 VNode,高效更新真实 DOM。
// 模板
<div>{{ message }}</div>
// 编译为渲染函数
function render() {
return h('div', this.message);
}
双向数据绑定
通过 v-model 实现表单元素与数据的双向绑定,本质是语法糖,结合 :value 和 @input。
<input v-model="message">
<!-- 等价于 -->
<input :value="message" @input="message = $event.target.value">
关键点总结
- 数据劫持:通过
Object.defineProperty或Proxy监听数据变化。 - 依赖收集:每个属性维护一个 Dep,收集依赖的 Watcher。
- 模板编译:将模板转为渲染函数,生成 VNode。
- 虚拟 DOM:通过 Diff 算法高效更新视图。
- 双向绑定:
v-model简化表单数据同步。







