Open hushicai opened 5 years ago
Fiber 有 child sibling return 三个节点 ,为什么说是“单向”链表?
Fiber 有 child sibling return 三个节点 ,为什么说是“单向”链表?
child、return是用来构建“树”,“sibling”用来构建同级元素的“单向”链表,通过遍历这个“单向”链表来 dom diff。
“我们可以随时停止遍历并稍后恢复。”
这个要怎么做到呢,如何停止、如何恢复
“我们可以随时停止遍历并稍后恢复。”
这个要怎么做到呢,如何停止、如何恢复
循环完全由程序负责了,当然可以根据各种条件,随时跳出循环,并择机恢复。
好的,理解了,那我觉得跳出循环简单,但要恢复的实现应该比较麻烦 😂
好的,理解了,那我觉得跳出循环简单,但要恢复的实现应该比较麻烦 😂
恢复也不麻烦,重新进入循环就好了,不过需要在循环外保存上次退出时的状态。
在处理UI时,如果一次执行太多工作,可能会导致动画丢帧。
基本上,如果React要同步遍历整个组件树,并为每个组件执行任务,它可能会运行超过16毫秒,这将导致不顺畅的视觉效果。
较新的浏览器(和React Native)实现了有助于解决这个问题的API:
requestIdleCallback
,可用于对函数进行排队,这些函数会在浏览器空闲时被调用:如果我现在打开控制台并执行上面的代码,Chrome会打印
49.9
和false
,它基本上告诉我,我有49.9ms
去做我需要做的任何工作,并且我还没有用完所有分配的时间,否则deadline.didTimeout
将会是true
。但
requestIdleCallback
实际上有点过于严格,并且执行频次不足以实现流畅的UI渲染,因此React团队必须实现自己的版本。现在,如果我们将React对组件执行的所有活动放入函数
performWork
, 并使用requestIdleCallback
来安排工作,我们的代码可能如下所示:我们对一个组件执行工作,然后返回要处理的下一个组件。
这是可以做到的,但前提是我们不能同步地处理整个组件树。
因此,我们需要一种方法将渲染工作分解为增量单元。
为了解决这个问题,React必须重新实现遍历树的算法,从依赖于内置堆栈的同步递归模型,变为具有链表和指针的异步模型。
递归遍历
递归方法直观,非常适合遍历树。
但是正如我们发现的,它有局限性:最大的一点就是我们无法分解工作为增量单元。
我们不能暂停特定组件的工作并在稍后恢复。
通过这种方法,React只能不断迭代直到它处理完所有组件,并且堆栈为空。
链表遍历
Sebastian Markbåge在Fiber Principles: Contributing To Fiber概括了该算法的要点。
要实现该算法,我们需要一个包含3个字段的数据结构:
在React新的协调算法的上下文中,包含这些字段的数据结构称为Fiber。
下图展示了通过链表链接的对象的层级结构和它们之间的连接类型:
它看起来像浏览器中的一个调用堆栈。
我们现在通过保持对
current
节点(充当顶部堆栈帧)的引用来控制堆栈:我们可以随时停止遍历并稍后恢复。