在react中,fiber链表是怎么遍历的?

手机游戏开发者 2024-9-25 05:12:27 38 0 来自 中国
Fiber是对react核心算法的重构,react16以上版本引入了fiber架构,此中的计划头脑很值得我们去学习。

那fiber是什么呢?


  • fiber是一个实行单位
  • fiber也是一种数据布局
在没引入fiber之前,React会递归比对VirtualDOM树,找出必要变更的节点,然后同步更新它们。这个过程React称为Reconciliation(调和)。在Reconciliation过程中,React会不停占用着欣赏器资源,如果更新节点庞大,那么用户触发的事故大概得不到回馈大概出现卡顿。

fiber的出现则是把庞大的更新节点分割为一个个小的任务单位,欣赏器可以在react和相应时间中切换控制权,从而到达优化效果。

fiber的可停止、继承是基于 欣赏器的 requestIdleCallback api实现的。现在大多欣赏装备每秒革新60次,requestIdleCallback 函数每一帧会返回这一秒渲染完成后剩余的时间,React就会查抄现在还剩多少时间,如果没偶然间就将控制权交还欣赏器;然后继承举行下一帧的渲染。

假造dom转化成fiber后,会有这几个属性,去指向下一个实行单位。


  • child(child指的是第一个子节点而不是全部的子节点)
  • sibling 指的是下一个兄弟节点(弟弟)
  • return 指向父节点
<div id="A1">  <div id="B1">     <div id="C1"></div>     <div id="C2"></div>  </div>  <div id="B2"></div><div>如许的jsx如果要转成fiber则会是这个样子
详情可以戳 -> 在react中,假造dom是怎样转化为fiber链表的?
// element.jslet A1 = { key: 'A1', type: 'div' }let B1 = { key: 'B1', type: 'div', return: A1 }let B2 = { key: 'B2', type: 'div', return: A1 }let C1 = { key: 'C1', type: 'div', return: B1 }let C2 = { key: 'C2', type: 'div', return: B1 }A1.child = B1B1.sibling = B2B1.child = C1C1.sibling = C2module.exports = A1
fiber的遍历顺序是由根节点开始的,优先级 child > sibling > return
所以遍历的先后顺序是


  • A1.child (B1)
  • B1.child (C1)
  • C1.sibling (C2) C1没有child了,就去找它的兄弟
  • C2.return (B1) C2 既没有child,又没有sibling,就去找它的 父节点 return
  • B1.sibling (B2) B1的child已经被遍历过了,就去找它的sibling
  • B2.return (A1)
开始遍历
let rootFiber = require('./element')let nextUnitOfWork = nullfunction workLoop() {  while(nextUnitOfWork) {    nextUnitOfWork = performUnitOfWork(nextUnitOfWork)  }}function performUnitOfWork(currentFiber) { // 返回下一个实行单位   beginWork(currentFiber)   if (currentFiber.child) {    return currentFiber.child  }  // 如果能走到这一步,证实遍历到 C1 了  while(currentFiber) { // 由于此处大概 sibling不肯定只有一个,所以要进入while循环    if(currentFiber.sibling) {      return currentFiber.sibling    }    // 如果没有sibling了,就会到其父节点    return currentFiber.return  }}function beginWork(currentFiber) {  // 本章重要纪录fiber是怎么遍历的,所以就不去做别的事情啦  console.log(currentFiber.key)}nextUnitOfWork = rootFiberworkLoop()写到这块是不是少了些什么东西呢?哦对,没有写怎么去让它变成可停止、可规复的遍历,那就必要祭出上面提出的requestIdleCallback了

我们只必要对workLoop作出小小改动即可

function workLoop(deadline) {    // timeRemaining() 是指当前渲染完留给react调理的时间    while ((deadline.timeRemaining() > 1 && nextUnitOfWork) {        nextUnitOfWork = performUnitOfWork(nextUnitOfWork);    }    if (!nextUnitOfWork) {        console.log('render阶段遍历竣事')    } else {        requestIdleCallback(workLoop, { timeout: 500 });    }}requestIdleCallback(workLoop, { timeout: 500 });timeout是指的超时时间,意思是,如果超过500ms还没做我的事的话,那你必须放动手头工作,立刻去继承实行workLoop。

如许我们关于fiber链表是怎么遍历的就完成啦!

资料参考: 从零实现React16 Fiber架构与Hooks源码
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 20:32, Processed in 0.354699 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表