413 words
2 minutes
从零手写一个 Mini React 框架
造轮子是最好的学习方式,本文带你手写一个 Mini React
目标
实现一个简化的 React 框架,包含以下核心功能:
- JSX 编译
- 虚拟 DOM
- 组件渲染
- 生命周期(useState, useEffect)
1. JSX 编译
// JSX -> createElement -> 虚拟DOMfunction 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);}完整代码
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 对象
- 状态管理通过闭包实现