模拟vue实现原理
Vue 实现原理的核心模块
Vue 的核心实现原理主要包括响应式系统、虚拟 DOM、模板编译和组件化机制。以下是模拟 Vue 这些核心功能的简化实现方法。
响应式系统
Vue 使用 Object.defineProperty 或 Proxy 实现数据劫持,监听数据变化并触发更新。
基于 Object.defineProperty 的简化实现:
function defineReactive(obj, key, val) {
const dep = new Dep(); // 依赖收集器
Object.defineProperty(obj, key, {
get() {
if (Dep.target) {
dep.addSub(Dep.target); // 收集依赖
}
return val;
},
set(newVal) {
if (newVal === val) return;
val = newVal;
dep.notify(); // 通知更新
},
});
}
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
class Watcher {
constructor(vm, key, updateFn) {
Dep.target = this;
vm[key]; // 触发 getter,收集依赖
Dep.target = null;
this.updateFn = updateFn;
}
update() {
this.updateFn();
}
}
虚拟 DOM 与 Diff 算法
虚拟 DOM 是一个轻量级的 JavaScript 对象,用于描述真实 DOM 结构。Diff 算法通过对比新旧虚拟 DOM 的差异,最小化 DOM 操作。
虚拟 DOM 的简化实现:
function createElement(tag, props, children) {
return { tag, props, children };
}
function render(vnode) {
if (typeof vnode === 'string') return document.createTextNode(vnode);
const el = document.createElement(vnode.tag);
for (const key in vnode.props) {
el.setAttribute(key, vnode.props[key]);
}
vnode.children.forEach(child => {
el.appendChild(render(child));
});
return el;
}
function patch(oldNode, newNode) {
if (oldNode.tag !== newNode.tag) {
return render(newNode); // 直接替换
}
const el = oldNode.el;
for (const key in newNode.props) {
if (newNode.props[key] !== oldNode.props[key]) {
el.setAttribute(key, newNode.props[key]);
}
}
const oldChildren = oldNode.children;
const newChildren = newNode.children;
for (let i = 0; i < Math.max(oldChildren.length, newChildren.length); i++) {
if (!oldChildren[i]) {
el.appendChild(render(newChildren[i]));
} else if (!newChildren[i]) {
el.removeChild(oldChildren[i].el);
} else {
patch(oldChildren[i], newChildren[i]);
}
}
return el;
}
模板编译
Vue 将模板编译为渲染函数,生成虚拟 DOM。以下是一个极简的模板编译示例:
function compile(template) {
const ast = parse(template); // 解析为 AST(抽象语法树)
const code = generate(ast); // 生成渲染函数代码
return new Function(`with(this) { return ${code} }`);
}
// 示例:简单插值表达式
function parse(template) {
return {
type: 'element',
tag: 'div',
children: [{
type: 'text',
content: `{{ message }}`
}]
};
}
function generate(ast) {
return `createElement("${ast.tag}", {}, [this.message])`;
}
组件化机制
Vue 组件是带有预定义选项的可复用实例。以下是组件注册和渲染的简化逻辑:
class Vue {
constructor(options) {
this.$options = options;
this._data = options.data();
this._initReactive();
this.$mount(options.el);
}
_initReactive() {
Object.keys(this._data).forEach(key => {
defineReactive(this, key, this._data[key]);
});
}
$mount(el) {
this.$el = document.querySelector(el);
const updateComponent = () => {
const vnode = this.$options.render.call(this);
patch(this.$el, vnode);
};
new Watcher(this, updateComponent);
}
}
// 使用示例
const app = new Vue({
el: '#app',
data: () => ({ message: 'Hello Vue' }),
render() {
return createElement('div', {}, [this.message]);
}
});
总结
- 响应式系统:通过数据劫持和依赖收集实现数据驱动视图。
- 虚拟 DOM:用 JavaScript 对象描述 DOM 结构,配合 Diff 算法高效更新视图。
- 模板编译:将模板转换为渲染函数,生成虚拟 DOM。
- 组件化:将 UI 拆分为独立可复用的组件实例。
以上是 Vue 核心原理的简化实现,实际 Vue 源码还包含更多优化和边界处理。







