fiber
2022-11-22 16:14:41
What
react16 后引入了一个非常重要的概念 fiber,先说下 fiber 是什么,fiber 翻译过来有构造的意思,在 react 项目中一个节点发生变化会引起 diff 去找到真正变化的部分,耗费大量时间,此时 js 会占据主线程去做对比导致无法正常的渲染页面,以致于页面卡顿、反应慢等,所以便出现了 fiber
在 fiber 出现之前的架构中,节点以树的形式保存,每个节点上有指向子节点的指针,当节点发生变化后,采用深度优先遍历找到两课树变化的部分,从根节点开始依次遍历该节点的所有节点,当一个节点的所有子节点遍历完成才认为该节点遍历完成,这是按照后序遍历的规则。
但是这样遍历必须一次性完成不可中断,如果发生中断,我们可以保留进行中节点的索引下次继续遍历该节点,但是没有办法找到其父节点,因为每个节点只保存了其子节点的指向,所以中断后只能从根节点重新遍历一遍,不能从断点处继续遍历
而 fiber 有了新的结构,每个节点有三个指针,child、sibling、return,分别指向第一个子节点、下一个兄弟节点、父节点,将每一个 fiber 对象联系起来,react针对不同的react element对象会产生不同种类(tag)的fiber对象,下面是tag与element的对应关系
js
export const FunctionComponent = 0 // 函数组件
export const ClassComponent = 1 // 类组件
export const IndeterminateComponent = 2 // 初始化时不知道是函数组件还是类组件
export const HostRoot = 3 // ReactDom.render()产生的根元素
export const HostPortal = 4 // createPortal产生的 Portal
export const HostComponent = 5 // dom元素 比如 <div>
export const HostText = 6 // 文本节点
export const Fragment = 7 // 对应 <React.Fragment>
export const Mode = 8 // 对应 <React.StrictMode>
export const ContextConsumer = 9 // 对应 <Context.Consumer>
export const ContextProvider = 10 // 对应 <Context.Provider>
export const ForwardRef = 11 // 对应 React.ForwardRef
export const Profiler = 12 // 对应 <Profiler>
export const SuspenseComponent = 13 // 对应 <Suspense>
export const MemoComponent = 14 // 对应 React.memo 返回的组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
同样的,遍历规则为从根节点开始遍历,依次遍历该节点的子节点和兄弟节点,如果都遍历完了就回到它的父节点,同样的按照后序遍历规则,这样的结构和规则更像是链表结构,与之前的树结构对比就会发现,节点的遍历顺序和完成顺序是一样的,但是当发生中断后,只要保留下当前节点的索引,中断是可以恢复的,因为每个节点都能找到其父节点的指向,这就是 react fiber 可中断的原因