1. 流程理解
js
你写代码 → 变成快递单 → 分拣包裹 → 派送包裹 → 重复优化
2.代码阶段
2.1代码编写阶段(开发者视角)
javascript
// 你写的组件代码(JSX)
function App() {
return (
<div className="box">
<h1>Hello</h1>
<button onClick={() => alert('Clicked!')}>Click</button>
</div>
)
}
2.2.编译转换(Babel 工作)
php
// 编译后的实际代码(JS)
function App() {
return React.createElement(
'div',
{ className: 'box' },
React.createElement('h1', null, 'Hello'),
React.createElement(
'button',
{ onClick: () => alert('Clicked!') },
'Click'
)
);
}
**
**比喻:就像把中文地址翻译成国际快递的标准格式
3. 核心渲染流程(快递站工作)
阶段1:创建虚拟快递单(Fiber树)
yaml
// React 内部创建的 Fiber 节点结构
{
type: 'div',
props: { className: 'box' },
child: {
type: 'h1',
props: null,
child: null,
sibling: {
type: 'button',
props: { onClick: fn },
child: null
}
}
}
比喻:每个包裹(组件/DOM节点)都有详细的快递单信息
阶段2:分拣包裹(协调阶段)
旧包裹单 vs 新包裹单 → 对比差异 → 标记需要更新的包裹
关键代码:
go
// 伪代码:对比新旧 Fiber 节点
function reconcileChildren(oldFiber, newElement) {
if (oldFiber.type !== newElement.type) {
// 类型不同 → 标记为替换
return { effectTag: 'REPLACE' }
} else {
// 属性不同 → 标记为更新
return { effectTag: 'UPDATE' }
}
}
阶段3:派送包裹(提交阶段)
ini
// 伪代码:应用变更到真实DOM
function commitWork(fiber) {
if (fiber.effectTag === 'PLACEMENT') {
// 创建新DOM节点
const dom = document.createElement(fiber.type);
parentDom.appendChild(dom);
} else if (fiber.effectTag === 'UPDATE') {
// 更新现有DOM属性
Object.keys(fiber.props).forEach(key => {
if (key !== 'children') {
dom[key] = fiber.props[key];
}
});
}
}
4. 优化机制(快递站效率升级)
4.1. 时间切片(Time Slicing)
生活场景:分拣员每处理5个包裹就抬头看看有没有紧急包裹
代码实现:
scss
function workLoop() {
while (有剩余时间() && 还有任务()) {
处理一个Fiber节点();
}
if (还有任务()) {
// 让出主线程,稍后继续
requestIdleCallback(workLoop);
}
}
4.2. 可中断渲染
生活场景:正在分拣普通包裹时,突然来了加急件,立刻停下处理加急件
代码示例:
javascript
// 用户点击按钮触发高优先级更新
button.addEventListener('click', () => {
// React 内部会中断当前渲染
scheduleCallback(ImmediatePriority, () => {
// 立即处理点击事件
});
});
4.3. 优先级调度
5. 完整流程示例
markdown
1. 你点击按钮 → 生成紧急快递单(高优先级更新)
2. 分拣员(React)暂停当前包裹分拣
3. 优先处理你的点击事件:
- 修改状态
- 生成新的虚拟快递单
4. 重新开始分拣:
- 对比新旧快递单差异
- 只更新变化的DOM部分
5. 界面瞬间更新,你感觉不到卡顿
6. 关键优化点总结
- 虚拟快递单(Virtual DOM) :避免直接操作真实DOM(就像不直接手写快递单)
- 双向链表结构:可以随时暂停/恢复分拣流程(Fiber节点互相连接)
- 优先级插队:紧急包裹优先处理(用户交互 > 数据更新)
- 分批处理:每帧只处理5ms任务(浏览器每秒60帧 ≈ 每帧16.6ms)