React Fiber 树思想,解决业务实际场景
创始人
2024-05-09 21:12:21
0

熟悉 Fiber 树结构

我们知道,React 从 V16 版本开始采用 Fiber 树架构来实现渲染和更新机制。

Fiber 在 React 源码中可以看作是一个任务执行单元,每个 React Element 都会有一个与之对应的 Fiber 节点。

Fiber 节点的核心数据结构如下:

type Fiber = {type: any, //类型 return: Fiber, //父节点child: Fiber, // 指向第一个子节点sibling: Fiber, // 指向下一个弟弟
} 

其中,以下三个属性可以构成 Fiber 树:

  • return 表示父 Fiber 节点(顶级元素没有 return 指针)
  • sibling 表示下一个兄弟 Fiber 节点(如果没有下一个兄弟节点,也就没有这个指针)
  • child 表示第一个子 Fiber 节点(如果没有第一个子节点,也就没有这个指针)。

举个例子,假如我们的组件结构如下:

function App() {return (
名称:明里人
) }

对应的 Fiber 树结构如下:

通过 Fiber 树结构我们可以很方便的查找一个节点的上级、下级和同级。

接下来我们一起来看看实际的业务场景。

业务场景

有时我们会去实现一些任务类的需求,任务自身存在 status 状态,比如进行中、逾期、完成状态,每个任务都可以通过完成按钮被完成。

假设现在有一个「任务流」作为第一级数据出现,它的子集由一个或多个「任务组」组成,作为第二级数据出现,任务组的子集由一个或多个「任务」组成,作为第三级数据出现。

现有需求如下:

第三级的「任务」在完成时更新自身状态,但要考虑同步上级节点的状态:

  • 如果当前任务所在的任务组下所有任务都已完成,更新当前「任务组」状态为完成;
  • 如果所有任务组及任务都已完成,更新「任务流」状态为完成。

当「任务流」处于完成状态时,UI 的体现可能如下:

思路:

我们要在每个任务完成后,判断同级任务是否都已完成,若都已完成,则将父级(任务组)状态更新为完成。

如果我们将现有的菜单树结构改造为 Fiber 树结构,通过 return 可以很方便的找到父节点,然后通过 child 和 sibling 可以很方便的查找任务组下的每一个任务,决定是否更新任务组状态。

代码实现如下:

// 1. taskFlowData 任务流数据
// 2. currentTaskData 当前完成的任务数据export const getFinishedStatus = (task) => task.status === 1; // 1 代表完成
export const setFinishedStatus = (task) => task.status = 1;// 首先,将当前任务的状态更新
setFinishedStatus(currentTaskData);// 第一步,将现有数据转换为 Fiber 树结构
const createNode = (value, parent) => ({ value, return: parent, child: null, sibling: null }
);
// 1-1. 创建 root fiber 根节点,即 任务流
const rootNode = createNode(taskFlowData, undefined);
let currentNode = rootNode, currentTaskNode = null;
// 1-2. child 存放的是任务组,为第二级数据创建 Fiber 节点
currentNode.value.child.forEach((taskGroup, taskGroupIndex) => {const node = createNode(taskGroup, rootNode);// 1-3. 建立关系taskGroupIndex === 0 ? (currentNode.child = node) : (currentNode.sibling = node);// 1-4. 为第三级任务创建 Fiber 节点taskGroup.child.forEach((task, taskIndex) => {const childNode = createNode(task, node);taskIndex === 0 ? (node.child = childNode) : (currentNode.sibling = childNode);currentNode = childNode;// 1-5. 记录当前任务对应的 Fiber 节点if (task.id === currentTaskData.id) currentTaskNode = currentNode;});currentNode = node;
});// 第二步,根据 Fiber 树结构,来查找并更新状态
let parentNode = currentTaskNode.return;
while (parentNode) {let isFinished = true;// 2-1. 找到第一个任务let workInprgress = parentNode.child;// 2-2. 从第一个任务开始,依次查看每个任务的状态while (workInprgress) {// 2-3. 如果查找的当前任务处于未完成状态,无需更新父级状态if (!getFinishedStatus(workInprgress.value)) {isFinished = false;break;}workInprgress = workInprgress.sibling;}// 2-4. 更新任务组状态,再向上查找,确定是否更新任务流状态if (isFinished) {setFinishedStatus(parentNode.value);parentNode = parentNode.return;} else {// 2-5. 任务组状态不需要更新,直接结束break;}
} 

最后

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

相关内容

热门资讯

2025“三农”成绩单|筑牢粮...   粮食安全,是“国之大者”。  10月23日,在北大荒集团黑龙江格球山农场有限公司一烘干厂,工人驾...
视频丨赏冰雕品美食 穿唐装游古...   随着元旦临近,不少地方已经提前开启了旅游市场的预热活动。在青海省西宁市城北区的北川青唐城,大型雾...
一线见闻丨一条通道串联三大都市...   “十五五”规划建议提出,要增强区域发展协调性,巩固提升粤港澳大湾区高质量发展动力源作用。广东省中...
爱奇艺回应充25年会员退费难:...   12月28日,话题“男子爱奇艺会员充了25年遇退费难”登上微博热搜。  12月25日,河南许昌,...
30日至2026年1月2日强冷...   央视网消息:据中央气象台网站消息,预计12月30日至2026年1月2日,强冷空气将影响中东部大部...
财政部:2026年继续安排资金...   财政部部长蓝佛安在12月27日至28日举行的全国财政工作会议上表示,明年财政将大力提振消费。深入...
(年终特稿)中国经济这一年:民...   中新社北京12月28日电 (记者 刘亮)2025年,中国民营经济迎风破浪前行,不断在新赛道上跑出...
欧洲最高火山时隔半年再次喷发   位于意大利西西里岛东岸的埃特纳火山于当地时间12月26日开始喷发。  12月27日的画面显示,火...
香港“兴”观察|创新赋能 提质...   茶餐厅老板投身“谷子经济”大受欢迎,钢铁公司用大数据传承焊接技艺,循环经济让零农药、零化肥蔬菜走...
铁路公安加强巡逻检查为多条新建...   近期,多条新建高铁陆续开通运营。各地铁路公安机关强化路地公安警务融合,加强与铁路企业协作,强化巡...