自己动手实现vue
实现 Vue 的核心功能
要实现一个简化版的 Vue,需要关注以下几个核心功能:数据响应式、模板编译、虚拟 DOM 和依赖收集。以下是一个分步实现的方案。
数据响应式
通过 Object.defineProperty 或 Proxy 实现数据劫持,监听数据变化并触发更新。以 Proxy 为例:
function reactive(data) {
return new Proxy(data, {
get(target, key) {
track(target, key); // 依赖收集
return target[key];
},
set(target, key, value) {
target[key] = value;
trigger(target, key); // 触发更新
return true;
}
});
}
依赖收集与触发
依赖收集系统用于记录数据与视图的依赖关系:
const targetMap = new WeakMap();
let activeEffect = null;
function track(target, key) {
if (!activeEffect) return;
let depsMap = targetMap.get(target);
if (!depsMap) targetMap.set(target, (depsMap = new Map()));
let dep = depsMap.get(key);
if (!dep) depsMap.set(key, (dep = new Set()));
dep.add(activeEffect);
}
function trigger(target, key) {
const depsMap = targetMap.get(target);
if (!depsMap) return;
const dep = depsMap.get(key);
if (dep) dep.forEach(effect => effect());
}
模板编译
将模板字符串转换为渲染函数:
function compile(template) {
// 简化版:替换插值表达式
const renderCode = template.replace(/\{\{(.*?)\}\}/g, (_, exp) => `_s(${exp.trim()})`);
return new Function('_s', `return ${renderCode}`);
}
虚拟 DOM 与渲染
实现一个简单的虚拟 DOM 和渲染逻辑:
function createElement(tag, props, children) {
return { tag, props, children };
}
function render(vnode, container) {
if (typeof vnode === 'string') {
container.textContent = vnode;
return;
}
const el = document.createElement(vnode.tag);
for (const [key, value] of Object.entries(vnode.props || {})) {
el.setAttribute(key, value);
}
(vnode.children || []).forEach(child => render(child, el));
container.appendChild(el);
}
组件系统
实现一个基础的组件类:
class Component {
constructor(options) {
this.$options = options;
this._data = reactive(options.data());
this._el = null;
this._update = () => {
const vnode = this.$options.render.call(this);
render(vnode, this._el);
};
effect(this._update);
}
mount(el) {
this._el = el;
this._update();
}
}
使用示例
const app = new Component({
data() {
return { message: 'Hello Vue' };
},
render() {
return createElement('div', null, this.message);
}
});
app.mount(document.getElementById('app'));
注意事项
- 上述实现是简化版,实际 Vue 源码更复杂,包含优化和边界处理。
- 现代 Vue 3 使用
Proxy代替Object.defineProperty实现响应式。 - 完整的 Vue 需要实现更多功能如指令、生命周期、组件通信等。







