js实现mvvm
实现 MVVM 模式的 JavaScript 核心方法
数据绑定实现
通过 Object.defineProperty 或 Proxy 实现数据劫持
// Proxy 实现
const data = { text: '' }
const proxy = new Proxy(data, {
set(target, key, value) {
target[key] = value
updateView(key, value)
return true
}
})
function updateView(key, value) {
console.log(`更新DOM: ${key} = ${value}`)
}
模板编译
使用文档片段编译 DOM 模板
function compile(template) {
const fragment = document.createDocumentFragment()
let node = document.querySelector(template)
while (node.firstChild) {
fragment.appendChild(node.firstChild)
}
// 替换模板变量
traverse(fragment)
document.querySelector(template).appendChild(fragment)
}
function traverse(node) {
if (node.nodeType === 3) { // 文本节点
node.nodeValue = node.nodeValue.replace(/\{\{(.*)\}\}/, (_, key) => {
return data[key.trim()]
})
}
}
观察者模式实现
建立依赖收集系统
class Dep {
constructor() {
this.subs = []
}
addSub(sub) {
this.subs.push(sub)
}
notify() {
this.subs.forEach(sub => sub.update())
}
}
class Watcher {
constructor(vm, exp, cb) {
this.vm = vm
this.exp = exp
this.cb = cb
this.value = this.get()
}
get() {
Dep.target = this
const value = this.vm.data[this.exp]
Dep.target = null
return value
}
update() {
this.cb(this.vm.data[this.exp])
}
}
完整 MVVM 框架结构
class MVVM {
constructor(options) {
this.$el = options.el
this.$data = options.data
// 数据代理
Object.keys(this.$data).forEach(key => {
this.proxyData(key)
})
// 数据响应式
observe(this.$data)
// 模板编译
new Compile(this.$el, this)
}
proxyData(key) {
Object.defineProperty(this, key, {
get() {
return this.$data[key]
},
set(newVal) {
this.$data[key] = newVal
}
})
}
}
实际应用示例
<div id="app">
<input v-model="message">
<p>{{ message }}</p>
</div>
<script>
const vm = new MVVM({
el: '#app',
data: {
message: 'Hello MVVM'
}
})
</script>
关键点总结:
- 数据劫持实现响应式
- 模板解析建立初始绑定
- 依赖收集系统跟踪变化
- 批量更新优化性能
以上实现展示了 MVVM 的核心原理,实际框架(如 Vue)会包含更多优化和功能扩展,如虚拟 DOM、指令系统、生命周期等。







