以下是用 TypeScript 实现简化版 React 的核心代码,包含虚拟 DOM、状态管理和协调更新机制:
// 类型定义
type VNode = {
type: string | Function;
props: Record<string, any>;
children: VNode[];
dom?: HTMLElement;
};
type Component = {
render: () => VNode;
__state?: any;
__hooks?: any[];
};
// 虚拟 DOM 创建函数
function createElement(
type: string | Function,
props: Record<string, any>,
...children: (VNode | string)[]
): VNode {
return {
type,
props,
children: children.map(child =>
typeof child === 'object' ? child : createTextElement(child)
)
};
}
function createTextElement(text: string): VNode {
return {
type: 'TEXT',
props: { nodeValue: text },
children: []
};
}
// 渲染器
let rootInstance: Component | null = null;
function render(vnode: VNode, container: HTMLElement) {
const prevInstance = rootInstance;
const nextInstance = reconcile(container, prevInstance, vnode);
rootInstance = nextInstance;
}
// 协调器
function reconcile(
parent: HTMLElement,
instance: Component | null,
vnode: VNode
): Component {
if (instance == null) {
// 创建新实例
const newInstance = instantiate(vnode);
parent.appendChild(newInstance.dom!);
return newInstance;
} else if (vnode == null) {
// 删除实例
parent.removeChild(instance.dom!);
return null!;
} else if (instance.vnode.type !== vnode.type) {
// 替换实例
const newInstance = instantiate(vnode);
parent.replaceChild(newInstance.dom!, instance.dom!);
return newInstance;
} else {
// 更新实例
instance.update(vnode);
return instance;
}
}
// 实例化组件
function instantiate(vnode: VNode): Component {
const { type, props } = vnode;
if (typeof type === 'function') {
// 函数组件
const component: Component = { __state: {}, __hooks: [] };
const child = type(props);
const instance = Object.assign(component, child);
instance.dom = createDom(child);
return instance;
}
// 原生 DOM 元素
const dom = document.createElement(type as string);
updateDom(dom, {}, props);
return {
type,
props,
dom,
update(vnode: VNode) {
updateDom(this.dom!, this.props, vnode.props);
this.props = vnode.props;
}
};
}
// DOM 更新函数
function updateDom(
dom: HTMLElement,
prevProps: Record<string, any>,
nextProps: Record<string, any>
) {
// 移除旧属性
Object.keys(prevProps)
.filter(isEvent)
.forEach(name => dom.removeEventListener(name.toLowerCase(), prevProps[name]));
// 设置新属性
Object.keys(nextProps)
.filter(isProperty)
.forEach(name => dom[name] = nextProps[name]);
// 绑定事件
Object.keys(nextProps)
.filter(isEvent)
.forEach(name => dom.addEventListener(name.toLowerCase(), nextProps[name]));
}
// 辅助函数
function isEvent(key: string): boolean {
return key.startsWith('on');
}
function isProperty(key: string): boolean {
return key !== 'children' && !isEvent(key);
}
// 状态管理
let hookIndex = 0;
function useState<T>(initialState: T): [T, (newState: T) => void] {
const instance = rootInstance!;
const hooks = instance.__hooks || (instance.__hooks = []);
const currentIndex = hookIndex++;
hooks[currentIndex] = hooks[currentIndex] || initialState;
const setState = (newState: T) => {
hooks[currentIndex] = newState;
// 触发重新渲染
render(instance.vnode, instance.dom!.parentNode!);
};
return [hooks[currentIndex], setState];
}
// 使用示例
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
// 渲染到 DOM
const root = document.getElementById('root')!;
render(<Counter />, root);关键实现要点:
这个实现展示了 React 的核心思想:
可以通过以下方式扩展功能:
注意:这是简化实现,实际 React 的完整实现包含更多优化和边界情况处理。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。