本系列的文章参考的源码是ReactV17
React架构
React@16之前
在React16之前,react的架构主要大致分为两层:
- Reconciler: 主要职责是对比查找更新前后的变化的组件;
- Renderer: 主要职责是基于变化渲染页面;
问题
在Reconciler中,mount的组件会调用mountComponent (),update的组件会调用updateComponent ()。这两个方法都会递归更新子组件。由于递归执行,所以更新一旦开始,中途就无法中断。当层级很深时,递归更新时间超过了16ms,用户交互就会卡顿。
React@16之后
为了解决这样的问题,React团队在React@16进行了重构,引入了新的架构模型:
- Reconciler: 主要职责是对比查找更新前后的变化的组件;
- Renderer: 主要职责是基于变化渲染页面;
- Scheduler: 主要职责是区分任务优先级,优先执行高优先级的任务;
新的架构在原来的基础上引入了Scheduler(调度器),这个东西是React团队参考浏览器的API:requestIdleCallback实现的。它的主要作用就是调度更新任务:
- 一方面可以中断当前任务执行更高优先级的任务;
- 另一方面能判断浏览器空闲时间,在恰当的时间将主动权给到浏览器,保证页面性能;并在浏览器下次空闲时继续之前中断的任务;
Fiber结构
你可以在下面图中看到Fiber节点属性
加入我们有下面这段代码
function App() {
return (
<div>
i am
<span>栗鼠怪</span>
</div>
)
}
以下是对应Fiber树的结构
上面每一个方块都对象一个Fiber节点,它们通过child, return, sibling连接对方构成一个Fiber树。
这里需要提一下,为什么父级指针叫做return而不是parent或者father呢?因为作为一个工作单元,return指节点执行完completeWork(后面系列文章后面会介绍)后会返回的下一个节点。子Fiber节点及其兄弟节点完成工作后会返回其父级节点,所以用return指代父级节点。
在结束本章前,我想介绍几个源码内的术语:
Reconciler工作的阶段被称为render阶段。因为在该阶段会调用组件的render方法。Renderer工作的阶段被称为commit阶段。就像你完成一个需求的编码后执行git commit提交代码。commit阶段会把render阶段提交的信息渲染在页面上。render与commit阶段统称为work,即React在工作中。相对应的,如果任务正在Scheduler内调度,就不属于work。
在后面我们会去了解Reconciler和Renderer的工作流程,所以章节名分别为render阶段和commit阶段。
总结
在本篇文章我们介绍了Fiber架构,这篇文章内容不多但启引导作用,为后面的文章做铺垫,之后我们会将render, commit,diff算法,hooks的实现,笔者也是刚开始学习react源码,希望做一个记录巩固这些内容。