vue实现mvvm原理
Vue实现MVVM原理的核心机制
Vue的MVVM实现主要依赖数据劫持结合发布者-订阅者模式,通过以下核心模块协同工作:
数据劫持(Observer)
通过Object.defineProperty或ES6的Proxy拦截对象属性的读写操作。当数据发生变化时,能触发setter通知依赖收集系统。
// 简化版数据劫持实现
function observe(data) {
Object.keys(data).forEach(key => {
let value = data[key]
Object.defineProperty(data, key, {
get() {
return value
},
set(newVal) {
if (newVal !== value) {
value = newVal
dep.notify() // 触发更新
}
}
})
})
}
依赖收集(Dep)
每个被劫持的属性都会拥有一个Dep实例,用于管理所有订阅该属性变化的Watcher。
class Dep {
constructor() {
this.subs = []
}
addSub(watcher) {
this.subs.push(watcher)
}
notify() {
this.subs.forEach(watcher => watcher.update())
}
}
订阅者(Watcher)
作为Observer和Compiler之间的桥梁,当数据变化时触发视图更新。每个表达式或指令都会对应一个Watcher实例。
class Watcher {
constructor(vm, exp, cb) {
this.vm = vm
this.exp = exp
this.cb = cb
this.value = this.get()
}
get() {
Dep.target = this
let value = this.vm[this.exp] // 触发getter
Dep.target = null
return value
}
update() {
this.cb.call(this.vm)
}
}
模板编译(Compiler)
解析模板中的指令和插值表达式,初始化视图并建立数据与DOM的绑定关系。
function compile(node, vm) {
if (node.nodeType === 1) { // 元素节点
compileElement(node, vm)
} else if (node.nodeType === 3) { // 文本节点
compileText(node, vm)
}
}
实现流程
- 初始化时通过Observer劫持所有数据
- 编译模板时遇到指令或插值会创建Watcher并添加到对应属性的Dep中
- 数据变化时通过setter触发Dep.notify()
- Watcher收到通知后执行更新操作
虚拟DOM优化
现代Vue版本引入虚拟DOM进行差异化更新:
- 将模板编译为渲染函数
- 数据变化时生成新的VNode
- 通过diff算法比对新旧VNode
- 最小化DOM操作
Proxy替代方案
Vue3使用Proxy替代Object.defineProperty,优势包括:
- 直接监听对象而非属性
- 可检测数组索引变化
- 支持Map/Set等新数据类型
- 性能更好
这种实现方式使得开发者只需关注数据逻辑,DOM更新由框架自动完成,实现了数据与视图的自动同步。







