413 words
2 minutes
从零手写一个 Mini React 框架

造轮子是最好的学习方式,本文带你手写一个 Mini React

目标#

实现一个简化的 React 框架,包含以下核心功能:

  • JSX 编译
  • 虚拟 DOM
  • 组件渲染
  • 生命周期(useState, useEffect)

1. JSX 编译#

// JSX -> createElement -> 虚拟DOM
function createElement(type, props, ...children) {
return {
type,
props: { ...props, children }
};
}
// 使用
const element = createElement(
'div',
{ className: 'container' },
createElement('h1', null, 'Hello')
);

2. 渲染函数#

function render(element, container) {
const dom = document.createElement(element.type);
// 处理属性
Object.keys(element.props).forEach(key => {
if (key !== 'children') {
dom[key] = element.props[key];
}
});
// 递归渲染子元素
element.props.children.forEach(child => {
render(child, dom);
});
container.appendChild(dom);
}

3. 实现 useState#

let state = null;
let index = 0;
function useState(initialValue) {
const currentIndex = index;
const currentState = state || initialValue;
const setState = (newValue) => {
state = newValue;
index = 0; // 重置索引
renderApp(); // 重新渲染
};
index++;
return [currentState, setState];
}

4. 实现 useEffect#

const effects = [];
function useEffect(callback, deps) {
const currentEffect = {
callback,
deps,
cleanup: null
};
const hasChanged = !effects.length ||
!deps.every((d, i) => d === effects[i].deps?.[i]);
if (hasChanged) {
// 执行清理函数
if (effects[effects.length - 1]?.cleanup) {
effects[effects.length - 1].cleanup();
}
// 执行副作用
currentEffect.cleanup = callback();
}
effects.push(currentEffect);
}

完整代码#

mini-react.js
const state = [];
let componentState = [];
export function useState(initialValue) {
const i = componentState.length;
componentState[i] = componentState[i] || initialValue;
const setState = (newValue) => {
componentState[i] = newValue;
// 触发重新渲染
};
return [componentState[i], setState];
}
export function render(vnode, container) {
const dom = document.createElement(vnode.type);
// 属性处理
Object.keys(vnode.props).forEach(key => {
if (key !== 'children') {
dom[key] = vnode.props[key];
}
});
// 子节点渲染
vnode.props.children?.forEach(child => {
render(child, dom);
});
container.appendChild(dom);
}
WARNING

这只是一个简化版本,真实的 React 还要处理 Fiber、Diff 算法、事务机制等复杂逻辑。

总结#

通过手写 Mini React,我们理解了:

  • JSX 的本质是函数调用
  • 虚拟 DOM 是普通 JS 对象
  • 状态管理通过闭包实现