实现vue vm
Vue VM 实现
Vue VM(ViewModel)是 Vue.js 的核心部分,负责连接视图(View)与数据模型(Model)。以下是实现 Vue VM 的关键步骤:
数据绑定
通过 Object.defineProperty 或 Proxy 实现数据劫持,监听数据变化。当数据变化时,自动更新视图。
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
return val;
},
set(newVal) {
if (newVal === val) return;
val = newVal;
// 触发更新
}
});
}
模板编译
将模板转换为渲染函数。使用正则表达式解析模板中的指令(如 v-model、v-if),生成对应的虚拟 DOM。
function compile(template) {
// 解析模板生成 AST
const ast = parse(template);
// 优化 AST
optimize(ast);
// 生成渲染函数
const code = generate(ast);
return new Function(`with(this){return ${code}}`);
}
依赖收集
通过 Dep 和 Watcher 实现依赖收集。每个响应式属性都有一个 Dep 实例,用于存储依赖的 Watcher。
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
class Watcher {
constructor(vm, expOrFn, cb) {
this.vm = vm;
this.getter = parsePath(expOrFn);
this.cb = cb;
this.value = this.get();
}
get() {
Dep.target = this;
const value = this.getter.call(this.vm, this.vm);
Dep.target = null;
return value;
}
update() {
this.run();
}
run() {
const value = this.get();
if (value !== this.value) {
this.value = value;
this.cb.call(this.vm, value);
}
}
}
虚拟 DOM 与 Diff 算法
通过虚拟 DOM 提高渲染效率。当数据变化时,生成新的虚拟 DOM,并通过 Diff 算法比较新旧虚拟 DOM,只更新变化的部分。
function patch(oldVnode, vnode) {
if (sameVnode(oldVnode, vnode)) {
patchVnode(oldVnode, vnode);
} else {
const parentElm = oldVnode.elm.parentNode;
createElm(vnode);
parentElm.insertBefore(vnode.elm, oldVnode.elm);
parentElm.removeChild(oldVnode.elm);
}
return vnode.elm;
}
生命周期管理
实现 Vue 的生命周期钩子,如 created、mounted、updated 等。在适当的时机调用这些钩子函数。
function callHook(vm, hook) {
const handlers = vm.$options[hook];
if (handlers) {
handlers.forEach(handler => handler.call(vm));
}
}
指令系统
实现常用指令如 v-model、v-for、v-if 等。指令负责将数据的变化反映到视图上。

function bindDirective(el, binding, vnode) {
switch (binding.name) {
case 'model':
el.value = binding.value;
el.addEventListener('input', e => {
vnode.context[binding.expression] = e.target.value;
});
break;
// 其他指令处理
}
}
以上是 Vue VM 的核心实现思路,实际开发中可以使用 Vue.js 官方库,无需手动实现这些功能。






