React Fiber 数据结构揭秘
此章节会通过两个 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
的原因。
相关链接
React Fiber 数据结构揭秘的更多相关文章
- React Fiber源码分析 (介绍)
写了分析源码的文章后, 总觉得缺少了什么, 在这里补一个整体的总结,输出个人的理解~ 文章的系列标题为Fiber源码分析, 那么什么是Fiber,官方给出的解释是: React Fiber是对核心算法 ...
- Omi架构与React Fiber
原文链接-https://github.com/AlloyTeam/omi/tree/master/tutorial 写在前面 Omi框架在架构设计的时候就决定把update的控制权交给了开发者,视灵 ...
- react fiber
react fiber https://github.com/acdlite/react-fiber-architecture https://github.com/facebook/react/is ...
- 瞧一瞧React Fiber
啥是React Fiber? React Fiber,简单来说就是一个从React v16开始引入的新协调引擎,用来实现Virtual DOM的增量渲染. 说人话:就是一种能让React视图更新过程变 ...
- React Fiber源码分析 第二篇(同步模式)
先附上两张流程图 1.scheduleRootUpdate 这个函数主要执行了两个操作 1个是创建更新createUpdate并放到更新队列enqueueUpdate, 1个是执行sheculeW ...
- React Fiber源码分析 第一篇
先附上流程图一张 先由babel编译, 调用reactDOM.render,入参为element, container, callback, 打印出来可以看到element,container,cal ...
- 你真的懂redis的数据结构了吗?redis内部数据结构和外部数据结构揭秘
Redis有哪些数据结构? 字符串String.字典Hash.列表List.集合Set.有序集合SortedSet. 很多人面试时都遇到过这种场景吧? 其实除了上面的几种常见数据结构,还需要加上数据结 ...
- React Fiber源码分析 第三篇(异步状态)
先附上流程图~ 调用setState时, 会调用classComponentUpdater的enqueueSetState方法, 同时将新的state作为payload参数传进 enqueueSetS ...
- redis内部数据结构和外部数据结构揭秘
Redis有哪些数据结构? 字符串String.字典Hash.列表List.集合Set.有序集合SortedSet. 很多人面试时都遇到过这种场景吧? 其实除了上面的几种常见数据结构,还需要加上数据结 ...
随机推荐
- PyQt4转换ui为py文件需添加如下代码才可执行
1)转换ui为py 命令行进入ui文件所在文件夹,输入pyuic4 ui_name.ui > py_name.py即可 或新建ui2py.bat文件,写入: @echo off @cd /d & ...
- web 基础设置
1.设置代码格式为UTF-8 2.运行jsp文档 3.设置自己喜欢的浏览器运行,设置为默认的 找到自己的浏览器位置 点ok Name是名字的意思 为这个浏览器娶一个名字 是什么浏览器就写什么名字 4. ...
- SPA 单页面应用程序。
看到这个问题,先说下自己的理解到的程度,再去参考做修正,争取这一次弄懂搞清楚 自己的理解: 单页面应用程序,解决浏览器获取数据刷新页面的尴尬,通过ajax请求获取数据达到异步更新视图的按钮,原理的实现 ...
- 2018面向对象程序设计(java)课程学习进度条
周次 (阅读/编写)代码行数 发布博文量/评论他人博文数量 课余学习时间 学习收获的最大程序阅读或编程任务 1 30-50 1/0 5 九九乘法表 2 60-80 1/0 6 实验一,实验二 3 12 ...
- 使用Bandwagon服务器ftp解决git clone速度慢的问题
写在前面 git clone速度往往很慢,我们可以先在身处美国的服务器上git clone,然后把文件用ftp传回来即可. 开始 我们以opencv为例 git clone https://githu ...
- JavaWeb学习路线
一.三大组件介绍 javaweb在开发中有三大组件分别提供不同的功能,这三大组件为servlet,filter,listener 1.servlet 简单来说就是客户端请求服务器和接受服务器的响应,狭 ...
- partial 的随笔
partial class Dmeos { public int Ager { get; set; } public void Run() { Console.WriteLine(Ager); } } ...
- iOS依赖库管理工具之Carthage
在iOS开发中,我们常会用CocoaPods来进行依赖库的管理.CoaoaPods 是一套整体解决方案,我们在 Podfile 中指定好我们需要的第三方库,然后 CocoaPods 就会进行下载,集成 ...
- MyEclipse最新版-版本更新说明及下载 - MyEclipse官方中文网
http://www.myeclipsecn.com/learningcenter/myeclipse-update/ [重要更新]MyEclipse 2015正式版发布 [重要更新]MyEclips ...
- i春秋官网4.0上线啦 文末有福利
爱瑞宝地(Everybody)期待了很久的 i春秋官网4.0上线啦 除了产品的功能更加完善 性能和体验也将大幅度提高 清新.舒适的视觉感受 搭配更加便捷的操作流程 只需一秒,扫码立即登录 即刻进入网络 ...