React Fiber 数据结构揭秘

您所在的位置:网站首页 电脑检测硬件的软件有哪些啊 React Fiber 数据结构揭秘

React Fiber 数据结构揭秘

2023-03-25 23:04| 来源: 网络整理| 查看: 265

image

个人博客

此章节会通过两个 demo 来展示 Stack Reconciler 以及 Fiber Reconciler 的数据结构。

image

首先用代码表示上图节点间的关系。比如 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 中,节点之间的关系可以用数据结构中的链表来表示。

节点之间的链表有三种情形, 用图表示如下:

image 父节点到子节点(红色虚线) 同层节点(黄色虚线) 子节点到父节点(蓝色虚线)

父节点指向第一个子节点, 每个子节点都指向父节点,同层节点间是单向链表。

首先, 构建节点的数据结构, 如下所示:

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 的原因。 相关链接 The how and why on React’s usage of linked list in Fiber to walk the component’s tree


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3