1. 响应式系统 (Reactivity)
这是最核心的部分,需要实现数据变化的自动检测和更新。
// 简单的响应式实现
class Reactive {
constructor() {
this.deps = new Map(); // 依赖收集
this.currentEffect = null;
}
// 数据劫持
observe(obj) {
const self = this;
return new Proxy(obj, {
get(target, key) {
// 依赖收集
self.track(target, key);
return target[key];
},
set(target, key, value) {
target[key] = value;
// 触发更新
self.trigger(target, key);
return true;
}
});
}
// 收集依赖
track(target, key) {
if (this.currentEffect) {
if (!this.deps.has(target)) {
this.deps.set(target, new Map());
}
if (!this.deps.get(target).has(key)) {
this.deps.get(target).set(key, new Set());
}
this.deps.get(target).get(key).add(this.currentEffect);
}
}
// 触发更新
trigger(target, key) {
const targetDeps = this.deps.get(target);
if (targetDeps && targetDeps.has(key)) {
targetDeps.get(key).forEach(effect => effect());
}
}
// 副作用函数
effect(fn) {
this.currentEffect = fn;
fn(); // 立即执行一次,收集依赖
this.currentEffect = null;
}
}
2. 虚拟 DOM (Virtual DOM)
// 虚拟节点
class VNode {
constructor(tag, props = {}, children = []) {
this.tag = tag;
this.props = props;
this.children = children;
this.el = null; // 对应的真实 DOM
}
}
// 创建虚拟节点
function h(tag, props, ...children) {
return new VNode(tag, props, children.flat());
}
// 渲染虚拟 DOM 到真实 DOM
function render(vnode, container) {
if (typeof vnode.tag === 'string') {
// 创建元素
const el = document.createElement(vnode.tag);
vnode.el = el;
// 设置属性
for (const key in vnode.props) {
if (key.startsWith('on')) {
// 事件处理
const event = key.slice(2).toLowerCase();
el.addEventListener(event, vnode.props[key]);
} else {
el.setAttribute(key, vnode.props[key]);
}
}
// 处理子节点
vnode.children.forEach(child => {
if (typeof child === 'string') {
el.appendChild(document.createTextNode(child));
} else {
render(child, el);
}
});
container.appendChild(el);
}
}
3. DOM Diff 算法
function diff(oldVNode, newVNode) {
if (!oldVNode) {
return { type: 'CREATE', newVNode };
}
if (!newVNode) {
return { type: 'REMOVE', oldVNode };
}
if (typeof oldVNode !== typeof newVNode || oldVNode.tag !== newVNode.tag) {
return { type: 'REPLACE', oldVNode, newVNode };
}
if (typeof oldVNode === 'string') {
if (oldVNode !== newVNode) {
return { type: 'TEXT', newText: newVNode };
}
return null;
}
const patches = [];
// 比较属性
const propsDiff = diffProps(oldVNode.props, newVNode.props);
if (propsDiff) {
patches.push({ type: 'PROPS', props: propsDiff });
}
// 比较子节点
const childrenDiff = diffChildren(oldVNode.children, newVNode.children);
if (childrenDiff.length > 0) {
patches.push({ type: 'CHILDREN', children: childrenDiff });
}
return patches.length > 0 ? patches : null;
}
function diffProps(oldProps, newProps) {
const patches = {};
// 检查新属性和修改的属性
for (const key in newProps) {
if (oldProps[key] !== newProps[key]) {
patches[key] = newProps[key];
}
}
// 检查删除的属性
for (const key in oldProps) {
if (!(key in newProps)) {
patches[key] = null;
}
}
return Object.keys(patches).length > 0 ? patches : null;
}
4. 模板编译系统
class TemplateCompiler {
compile(template) {
// 解析模板为 AST
const ast = this.parse(template);
// 生成渲染函数
return this.generate(ast);
}
parse(template) {
// 简化的模板解析器
const tagReg = /<(\w+)([^>]*)>(.*?)</\1>/gs;
const textReg = /{{(.*?)}}/g;
return {
type: 'element',
tag: 'div',
children: this.parseChildren(template)
};
}
parseChildren(content) {
const children = [];
const tagReg = /<(\w+)([^>]*)>(.*?)</\1>/g;
let lastIndex = 0;
let match;
while ((match = tagReg.exec(content)) !== null) {
// 处理文本节点
if (match.index > lastIndex) {
const text = content.slice(lastIndex, match.index).trim();
if (text) {
children.push({
type: 'text',
content: text
});
}
}
// 处理元素节点
children.push({
type: 'element',
tag: match[1],
props: this.parseProps(match[2]),
children: this.parseChildren(match[3])
});
lastIndex = match.index + match[0].length;
}
return children;
}
generate(ast) {
return `
function render(data) {
return ${this.generateNode(ast)};
}
`;
}
generateNode(node) {
if (node.type === 'element') {
const children = node.children.map(child => this.generateNode(child)).join(',');
return `h('${node.tag}', ${JSON.stringify(node.props)}, [${children}])`;
} else if (node.type === 'text') {
// 处理插值表达式
const content = node.content.replace(/{{(.*?)}}/g, '${data.$1}');
return ``${content}``;
}
}
}
5. 组件系统
class Component {
constructor(options = {}) {
this.data = this.reactive.observe(options.data || {});
this.template = options.template;
this.methods = options.methods || {};
this.mounted = options.mounted;
this.reactive = new Reactive();
this.compiler = new TemplateCompiler();
this.render = this.compileTemplate();
this.oldVNode = null;
}
compileTemplate() {
const renderCode = this.compiler.compile(this.template);
return new Function('h', 'data', renderCode + '; return render(data);');
}
mount(container) {
this.reactive.effect(() => {
const newVNode = this.render(h, this.data);
if (!this.oldVNode) {
render(newVNode, container);
} else {
const patches = diff(this.oldVNode, newVNode);
if (patches) {
patch(this.oldVNode.el, patches);
}
}
this.oldVNode = newVNode;
});
if (this.mounted) {
this.mounted.call(this);
}
}
}
// 使用示例
const app = new Component({
template: `
<div>
<h1>{{title}}</h1>
<p>{{message}}</p>
<button onclick="increment">Count: {{count}}</button>
</div>
`,
{
title: 'My Vue Clone',
message: 'Hello World',
count: 0
},
methods: {
increment() {
this.count++;
}
},
mounted() {
console.log('Component mounted');
}
});
app.mount(``document``.getElementById(``'app'``));
6. 生命周期管理
class Lifecycle {
constructor() {
this.hooks = {
beforeCreate: [],
created: [],
beforeMount: [],
mounted: [],
beforeUpdate: [],
updated: [],
beforeDestroy: [],
destroyed: []
};
}
callHook(name, ...args) {
if (this.hooks[name]) {
this.hooks[name].forEach(hook => hook.call(this, ...args));
}
}
addHook(name, fn) {
if (this.hooks[name]) {
this.hooks[name].push(fn);
}
}
}
7. 指令系统
class Directive {
static directives = new Map();
static register(name, definition) {
this.directives.set(name, definition);
}
static get(name) {
return this.directives.get(name);
}
}
// 内置指令
Directive.register('if', {
bind(el, binding) {
this.placeholder = document.createComment('v-if');
el.parentNode.insertBefore(this.placeholder, el);
this.el = el;
},
update(value) {
if (value) {
this.placeholder.parentNode.replaceChild(this.el, this.placeholder);
} else {
this.el.parentNode.replaceChild(this.placeholder, this.el);
}
}
});
Directive.register('show', {
update(el, value) {
el.style.display = value ? '' : 'none';
}
});
8. 核心架构整合
class MiniVue {
constructor(options = {}) {
this.options = options;
this.components = new Map();
this.directives = new Map();
// 初始化全局 API
this.initGlobalAPI();
}
initGlobalAPI() {
this.component = (name, definition) => {
this.components.set(name, definition);
};
this.directive = (name, definition) => {
this.directives.set(name, definition);
};
}
createApp(rootComponent) {
return {
mount: (container) => {
const instance = new Component(rootComponent);
instance.mount(typeof container === 'string'
? document.querySelector(container)
: container);
return instance;
}
};
}
}
// 使用
const Vue = new MiniVue();
const app = Vue.createApp({
template: '<div>{{message}}</div>',
{ message: 'Hello Mini Vue!' }
});
app.mount('#app');
关键技术要点总结
- 响应式系统: Proxy/Object.defineProperty + 依赖收集
- 虚拟DOM: 抽象DOM表示 + 高效diff算法
- 模板编译: 模板语法 → 渲染函数
- 组件系统: 可复用的UI单元
- 生命周期: 组件状态管理
- 指令系统: DOM操作抽象
- 事件系统: 统一的事件处理
- 插件系统: 功能扩展机制
实现顺序建议:响应式 → 虚拟DOM → 模板编译 → 组件系统 → 其他特性。