目录
Fiber Reconciler 【react v16.13.1】
React Fiber需要解决的问题
React Fiber的数据结构
时间分片
Fiber Reconciler 的调度
双缓冲 池概念
小节
练习
Fiber Reconciler 【react v16.13.1】
Fiber 协调 优化了栈协调的事务性弊端引起的卡顿
React Fiber需要解决的问题
- 可阻断的渲染过程
- 适时重启渲染
- 父子组件中来回切换布局更新
- 更清晰的错误处理
React Fiber的数据结构
- React Fiber将之前的DOM节点树用链表的结构来描述,与React15.x之前的版本不一样。
- React 15.x中描述DOM节点数的‘VDom’是一个对象(嵌套)。
- 而在React 16.x中是用Fiber节点来描述的。Fiber节点的数据结构就是一个链表。
// 来源 react-reconciler包
function FiberNode() {
// Fiber 单链表
this.return = null;// 返回替换旧值,更新反馈给根节点【自己执行完,返回给父节点】
this.child = null;// 子节点
this.sibling = null;// 兄弟节点
this.index = 0;// 顺序
// ...
}
Fiber Node结构示意图
- render阶段
执行组件的render方法(函数组件对应return),dom diff 确定哪些需要更新。Reconciler【协调阶段】此过程是可以被打断的。
- commit阶段
更新阶段,在确定更新内容后,提交更新并调用对应渲染模块(react-dom)进行渲染。【这个过程用户是看的见的】为了防止页面抖动,该过程是同步且不能被打断。【如果是异步,会存在延迟】
时间分片
React 在挂载或者更新过程中会做很多事情,比如调用组件的渲染函数、对比前后树差异,而且commit阶段是同步的,所以在Stack Reconciler中会导致卡顿等问题。
// 用权重进行区分:
export const ImmediatePriority: ReactPriorityLevel = 99;// 立即执行权重
// 用户阻断权重【如:拖动、事件点击,明显会阻断UI】
export const UserBlockingPriority: ReactPriorityLevel = 98;
export const NormalPriority: ReactPriorityLevel = 97;// 普通任务权重
export const LowPriority: ReactPriorityLevel = 96;// 比普通任务低级一点
export const IdlePriority: ReactPriorityLevel = 95;// 空闲时执行的
// NoPriority is the absence of priority. Also React-only.
export const NoPriority: ReactPriorityLevel = 90;// 保留项,平时不会用到
- requestAnimationFrame
requestAnimationFrame在做动画时经常用到,保障用户体验。Priority(优先级)较高的任务用requestAnimationFrame执行。
- requestIdleCallback【MDN web docs中可查看】
浏览器提供的闲时调用。requestIdleCallback()方法将在浏览器的空闲时段内调用的函数排队。这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应。
Fiber Reconciler 的调度
Reconciler
Fiber Node 在具体挂载&更新的过程中关键代码如下
function performUnitOfWork(unitOfWork: Fiber): Fiber | null {
// ... 代码
const current = unitOfWork.alternate;
let next;
if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) {
startProfilerTimer(unitOfWork);
next = beginWork(current, unitOfWork, renderExpirationTime);
stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);
} else {
next = beginWork(current, unitOfWork, renderExpirationTime);
}
// ... 代码
if (next === null) {
next = completeUnitOfWork(unitOfWork);
}
ReactCurrentOwner.current = null;
return next;
}
function completeUnitOfWork(unitOfWork: Fiber): Fiber | null {
// ...
completeWork();
}
a1->b1->b2->c1->d1->d2->d1->c1->b2->b3->c2->b3->b2->b1->a1
双缓冲 池概念
Fiber Reconciler过程中,内存中保持着两棵树:
current Tree【如cpu呈现给用户的存储】 & workInProcess Tree。【相当于高速缓冲存储,执行更新,render();更新完毕的节点映射给current Tree中对应节点】
当workInProcess Tree中执行完毕就转为current Tree。如果执行过程中被打断或者响应更高优先级的任务,也能在 workInProcess Tree中继续开始。
小节
React 15.x:React协调机制
React 16.x: React Fiber结构 React新协调机制
练习
阅读源码 React v16.13.1 版本 重点读 react-reconciler ReactFiber.js(react-reconciler/src/ReactFiber.js)。
产出:
Fiber Node 属性的注解表