js mvvm实现
MVVM 模式简介
MVVM(Model-View-ViewModel)是一种前端架构模式,通过数据绑定实现视图(View)与数据模型(Model)的分离,ViewModel 作为中间层负责处理业务逻辑和状态管理。
核心实现步骤
数据劫持(响应式原理)
使用 Object.defineProperty 或 Proxy 监听数据变化,触发更新:
// Proxy 实现
const reactive = (obj) => {
return new Proxy(obj, {
get(target, key) {
return Reflect.get(target, key);
},
set(target, key, value) {
Reflect.set(target, key, value);
console.log(`数据更新: ${key} = ${value}`);
// 触发视图更新
return true;
}
});
};
模板编译
解析 DOM 模板,替换插值表达式(如 {{data}})并建立依赖关系:
function compile(el, vm) {
const nodes = el.childNodes;
nodes.forEach(node => {
if (node.nodeType === 3) { // 文本节点
const text = node.textContent;
const reg = /\{\{(.*?)\}\}/g;
if (reg.test(text)) {
const key = RegExp.$1.trim();
node.textContent = vm.data[key];
// 监听数据变化并更新视图
new Watcher(vm, key, (val) => {
node.textContent = val;
});
}
}
});
}
依赖收集(发布-订阅)
通过 Dep 和 Watcher 实现数据变化的订阅与通知:
class Dep {
constructor() {
this.subs = [];
}
addSub(watcher) {
this.subs.push(watcher);
}
notify() {
this.subs.forEach(watcher => watcher.update());
}
}
class Watcher {
constructor(vm, key, cb) {
this.vm = vm;
this.key = key;
this.cb = cb;
Dep.target = this; // 标记当前 Watcher
this.value = vm.data[key]; // 触发 getter 收集依赖
Dep.target = null;
}
update() {
this.value = this.vm.data[this.key];
this.cb(this.value);
}
}
整合 ViewModel
将数据劫持、模板编译和依赖收集结合:
class MVVM {
constructor(options) {
this.data = reactive(options.data); // 响应式数据
this.el = document.querySelector(options.el);
compile(this.el, this); // 编译模板
}
}
使用示例
<div id="app">{{message}}</div>
<script>
const vm = new MVVM({
el: '#app',
data: { message: 'Hello MVVM!' }
});
setTimeout(() => {
vm.data.message = 'Data changed!'; // 触发视图更新
}, 1000);
</script>
注意事项
- 现代框架(如 Vue 3)使用
Proxy替代Object.defineProperty,支持深层对象监听。 - 虚拟 DOM 可优化直接操作 DOM 的性能问题。
- 双向绑定可通过
v-model等指令扩展实现。







