vue mvvm的实现
Vue MVVM 的实现原理
Vue 的 MVVM(Model-View-ViewModel)模式通过数据绑定和响应式系统实现视图与数据的自动同步。以下是核心实现机制:
数据劫持(响应式核心)
Vue 使用 Object.defineProperty(Vue 2)或 Proxy(Vue 3)劫持数据对象的属性访问。当数据变化时,触发依赖更新。
Vue 2 示例:
Object.defineProperty(obj, key, {
get() {
// 收集依赖
return val;
},
set(newVal) {
// 触发更新
val = newVal;
}
});
Vue 3 示例:
new Proxy(data, {
get(target, key) {
// 收集依赖
return Reflect.get(target, key);
},
set(target, key, value) {
// 触发更新
return Reflect.set(target, key, value);
}
});
依赖收集与派发更新
- 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() {
// 触发组件重新渲染
}
}
虚拟 DOM 与 Diff 算法
Vue 通过虚拟 DOM 优化渲染性能:
- 将模板编译为渲染函数,生成虚拟 DOM。
- 数据变化时,对比新旧虚拟 DOM(Diff 算法),最小化 DOM 操作。
// 简化的 Diff 示例
function patch(oldVnode, newVnode) {
if (sameVnode(oldVnode, newVnode)) {
// 复用节点并更新差异
} else {
// 替换节点
}
}
模板编译
Vue 将模板编译为渲染函数:
- 解析:将模板转换为 AST(抽象语法树)。
- 优化:标记静态节点。
- 生成代码:将 AST 转换为可执行的渲染函数。
// 编译结果示例
function render() {
with(this) {
return _c('div', { attrs: { "id": "app" } }, [_v("Hello " + _s(name))]);
}
}
双向数据绑定(v-model)
v-model 是语法糖,结合 :value 和 @input 实现:
<input v-model="message">
<!-- 等价于 -->
<input :value="message" @input="message = $event.target.value">
关键设计思想
- 数据驱动:视图变化由数据变化自动触发。
- 组件化:每个组件实例对应一个 Watcher,实现局部更新。
- 异步更新队列:同一事件循环内的数据变化合并为一次更新。







