内容简介:此章节会通过两个
此章节会通过两个 demo 来展示 Stack Reconciler 以及 Fiber Reconciler 的数据结构。
首先用代码表示上图节点间的关系。比如 a1 节点 下有 b1、b2、b3 节点 , 就可以把它们间的关系写成 a1.render = () => [b1, b2, b3] ;
var a1 = { name: 'a1', render = () => [b1, b2, b3] }
var b1 = { name: 'b1', render = () => [c1] }
var b2 = { name: 'b2', render = () => [c2] }
var b3 = { name: 'b3', render = () => [] }
var c1 = { name: 'c1', render = () => [d1] }
var c2 = { name: 'c2', render = () => [] }
var d1 = { name: 'd1', render = () => [d2] }
var d2 = { name: 'd2', render = () => [] }
Stack Reconciler
在 React 16 之前,节点之间的关系可以用数据结构中 树的深度遍历 来表示。
如下实现 walk 函数, 将深度遍历的节点打印出来。
walk(a1)
function walk(instance) {
if (!instance) return
console.log(instance.name)
instance.render().map(walk)
}
输出结果为: a1 b1 c1 d1 d2 b2 c2 b3
Fiber Reconciler
在 React 16 中,节点之间的关系可以用数据结构中的 链表 来表示。
节点之间的链表有三种情形, 用图表示如下:
- 父节点到子节点(红色虚线)
- 同层节点(黄色虚线)
- 子节点到父节点(蓝色虚线)
父节点指向第一个子节点, 每个子节点都指向父节点,同层节点间是单向链表。
首先, 构建节点的数据结构, 如下所示:
var FiberNode = function(instance) {
this.instance = instance
this.parent = null
this.sibling = null
this.child = null
}
然后创建一个将节点串联起来的 connect 函数:
var connect = function(parent, childList) {
parent.child = childList.reduceRight((prev, current) => {
const fiberNode = new FiberNode(current)
fiberNode.parent = parent
fiberNode.sibling = prev
return fiberNode
}, null)
return parent.child
}
在 JavaScript 中实现链表的数据结构可以巧用 reduceRight
connect 函数中实现了上述链表关系。可以像这样使用它:
var parent = new FiberNode(a1) var childFirst = connect(parent, a1.render())
这样子便完成了 a1 节点 指向 b1 节点 的链表、 b1、b2、b3 节点间 的单向链表以及 b1、b2、b3 节点 指向 a1 节点 的链表。
最后剩下 goWalk 函数将全部节点给遍历完。
// 打印日志以及添加列表
var walk = function(node) {
console.log(node.instance.name)
const childLists = node.instance.render()
let child = null
if (childLists.length > 0) {
child = connect(node, childLists)
}
return child
}
var goWalk = function(root) {
let currentNode = root
while (true) {
const child = walk(currentNode)
// 如果有子节点
if (child) {
currentNode = child
continue
}
// 如果没有相邻节点, 则返回到父节点
while (!currentNode.sibling) {
currentNode = currentNode.parent
if (currentNode === root) {
return
}
}
// 相邻节点
currentNode = currentNode.sibling
}
}
// 调用
goWalk(new FiberNode(a1))
打印结果为 a1 b1 c1 d1 d2 b2 c2 b3
Fiber Reconciler 的优势
通过分析上述两种数据结构实现的代码,可以得出下面结论:
- 基于树的深度遍历实现的 Reconciler: 一旦进入调用栈便无法暂停;
- 基于链表实现的 Reconciler: 在
while(true) {}的循环中, 可以通过currentNode的赋值重新得到需要操作的节点,而在赋值之前便可以'暂停'来执行其它逻辑, 这也是requestIdleCallback能得以在Fiber Reconciler的原因。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
代码整洁之道:程序员的职业素养
罗伯特·C.马丁 (Robert C.Martin) / 余晟、章显洲 / 人民邮电出版社 / 2016-9-1 / 49.00元
1. 汇聚编程大师40余年编程生涯的心得体会 2. 阐释软件工艺中的原理、技术、工具和实践 3. 助力专业软件开发人员具备令人敬佩的职业素养 成功的程序员在以往的工作和生活中都曾经历过大大小小的不确定性,承受过永无休止的压力。他们之所以能够成功,是因为拥有一个共同点,都深切关注创建软件所需的各项实践。他们将软件开发视为一种需要精雕细琢加以修炼的技艺,他们以专业人士的标准要求自己,......一起来看看 《代码整洁之道:程序员的职业素养》 这本书的介绍吧!