js 实现mvvm
MVVM 模式简介
MVVM(Model-View-ViewModel)是一种前端架构模式,通过数据绑定实现视图(View)与数据模型(Model)的分离。ViewModel 作为中间层,负责处理业务逻辑和数据绑定,使开发者无需直接操作 DOM。
核心实现步骤
数据劫持(响应式数据)
通过 Object.defineProperty 或 Proxy 监听数据变化,触发更新逻辑。

function observe(data) {
if (!data || typeof data !== 'object') return;
return new Proxy(data, {
get(target, key) {
return target[key];
},
set(target, key, value) {
target[key] = value;
notifyUpdate(); // 触发视图更新
return true;
}
});
}
模板编译
解析 HTML 模板中的指令(如 v-model、{{}}),将数据绑定到视图。
function compile(el, vm) {
const fragment = document.createDocumentFragment();
let child;
while (child = el.firstChild) {
fragment.appendChild(child);
}
// 替换模板中的插值表达式
const reg = /\{\{(.*?)\}\}/g;
fragment.textContent = fragment.textContent.replace(reg, (match, key) => {
return vm.data[key.trim()];
});
el.appendChild(fragment);
}
依赖收集与更新
实现一个简单的依赖管理器(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, callback) {
this.vm = vm;
this.key = key;
this.callback = callback;
Dep.target = this;
this.vm.data[this.key]; // 触发 getter,收集依赖
Dep.target = null;
}
update() {
this.callback(this.vm.data[this.key]);
}
}
双向绑定实现
通过 v-model 指令实现表单元素与数据的双向绑定。
function bindInput(el, vm, key) {
el.addEventListener('input', (e) => {
vm.data[key] = e.target.value;
});
new Watcher(vm, key, (value) => {
el.value = value;
});
}
完整示例
以下是一个极简的 MVVM 实现框架:
class MVVM {
constructor(options) {
this.data = observe(options.data());
this.el = document.querySelector(options.el);
compile(this.el, this);
}
}
// 使用示例
const vm = new MVVM({
el: '#app',
data: () => ({ message: 'Hello MVVM!' })
});
注意事项
- 现代框架(如 Vue 3)使用
Proxy替代Object.defineProperty,性能更好且支持数组监听。 - 实际项目中需处理复杂指令(如
v-for)、虚拟 DOM 等优化。 - 可结合
Virtual DOM库(如 Snabbdom)实现高效视图更新。






