js mvvm 实现
MVVM 实现原理
MVVM(Model-View-ViewModel)是一种前端架构模式,通过数据绑定实现视图与数据的自动同步。核心在于ViewModel作为中间层,连接View和Model。
核心实现步骤
数据劫持(响应式)
通过Object.defineProperty或Proxy监听数据变化:
// Proxy实现
const data = { text: '' };
const handler = {
set(target, key, value) {
target[key] = value;
updateView(); // 触发视图更新
return true;
}
};
const viewModel = new Proxy(data, handler);
模板编译
解析DOM模板中的指令(如v-model)并建立绑定关系:
function compile(el) {
const nodes = el.querySelectorAll('[v-model]');
nodes.forEach(node => {
const key = node.getAttribute('v-model');
node.addEventListener('input', (e) => {
viewModel[key] = e.target.value; // 数据变更触发Proxy.set
});
node.value = viewModel[key]; // 初始化值
});
}
依赖收集 通过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;
vm[key]; // 触发getter收集依赖
Dep.target = null;
}
update() { this.cb(this.vm[this.key]); }
}
完整示例实现
class MiniVue {
constructor(options) {
this.$el = document.querySelector(options.el);
this.$data = options.data();
this.observe(this.$data);
this.compile(this.$el);
}
observe(data) {
const dep = new Dep();
Object.keys(data).forEach(key => {
let value = data[key];
Object.defineProperty(data, key, {
get() {
Dep.target && dep.addSub(Dep.target);
return value;
},
set(newVal) {
value = newVal;
dep.notify();
}
});
});
}
compile(el) {
const childNodes = el.childNodes;
childNodes.forEach(node => {
if (node.nodeType === 3) { // 文本节点
const text = node.textContent;
const reg = /\{\{(.*?)\}\}/;
if (reg.test(text)) {
const key = RegExp.$1.trim();
new Watcher(this.$data, key, val => {
node.textContent = text.replace(reg, val);
});
node.textContent = text.replace(reg, this.$data[key]);
}
}
});
}
}
关键优化点
虚拟DOM Diff 复杂场景下可引入虚拟DOM提高性能:
function createVNode(tag, props, children) {
return { tag, props, children };
}
function diff(oldVNode, newVNode) {
// 实现差异对比算法
}
批量异步更新
使用Promise或MutationObserver合并多次更新:
let pending = false;
function queueUpdate() {
if (!pending) {
pending = true;
Promise.resolve().then(() => {
updateView();
pending = false;
});
}
}
以上实现展示了MVVM的核心机制,实际框架(如Vue)会包含更多优化和功能扩展。







