我的编程空间,编程开发者的网络收藏夹
学习永远不晚

一文掌握React 组件树遍历技巧

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

一文掌握React 组件树遍历技巧

引言

本文对应的 react 版本是 18.2.0

下面的 dom 结构react 内部是如何遍历的

const App = () => {
  return (
    <div>
      <button>+1</button>
      <A count={0} />
    </div>
  );
};
const A = (props) => {
  useEffect(() => {
    console.log(props.count);
  }, [props.count]);
  return <div>{props.count}</div>;
};

react 内部遍历核心逻辑:

  • render 时调用 commitPassiveUnmountOnFiber 函数
  • commitPassiveUnmountOnFiber 处理不同的 WorkTag,并调用 recursivelyTraversePassiveUnmountEffects
  • recursivelyTraversePassiveUnmountEffects 根据当前 Fiber 的子节点有没有 passive effectuseEffectuseLayoutEffect)来决定是否遍历当前 Fiber 的子节点
    • 如果子节点有 passive effect,则优先遍历子节点 (深度优先),直到找到最终的叶子节点,退出当前循环
    • 然后进入兄弟节点,开始遍历兄弟节点的子节点
      • 具体从哪个兄弟节点开始遍历,react 选择的是离退出循环的那个叶子节点的父节点,检查有没有子节点,以此循环遍历
    • 直到最后找到所有有 passive effect 的节点

代码简化:

commitPassiveUnmountOnFiber(root.current);
function commitPassiveUnmountOnFiber(finishedWork) {
  // 省略了处理不同的 WorkTag
  recursivelyTraversePassiveUnmountEffects(finishedWork);
}
function recursivelyTraversePassiveUnmountEffects(parentFiber) {
  // 省略了其他处理
  if (parentFiber.subtreeFlags & PassiveMask) {
    let child = parentFiber.child;
    while (child !== null) {
      commitPassiveUnmountOnFiber(child);
      child = child.sibling;
    }
  }
}

所以对于这段 dom 的遍历逻辑是:

  • 首先从根组件开始 FiberRootNode,取到 current
    • 也就是说 FiberRootNode.currentdiv#root 这是一个 fiber,它的 tag3
  • 由于 App 的子组件有 passive effect,所以会进入 App 组件,它的 tag0
  • App 组件中节点是 <div><di >tag5
    • <div> 下面有两个子元素 <button><A>
  • 先遍历 <button> 它的 tag5
  • <button> 内部只有一个文本节点,没有 passive effect
    • 所以 react 不遍历了(跳出当前遍历的循环,也就是 button 这条不在遍历了)
  • 跳出循环后,查看 button 的兄弟节点,它的兄弟节点是 <A><A>tag0
  • 由于 <A> 节点的子节点没有 passive effect,所以跳出循环,结束整个遍历

总结

  • 从跟节点开始遍历
  • 当前组件的子组件有没有 passive effect
  • 采取深度优先
  • 如果 dom 节点内有函数组件,则这个 dom 会被遍历,否则不会遍历
  • 如果当前 fiber 下的所有子 fiber 都没有 passive effect ,则这一整个都链表都不会被遍历
  • 如果当前 fiber 只有 dom,则这些 dom 也不会遍历

总的来说组件会不会别遍历看 fiber 有没有 passive effect

  • 有,一定会被遍历
  • 没有,下面两种情况会被遍历,其他情况不会被遍历
    • passive effect 的父组件
    • passive effect 组件是兄弟组件

passive effect 指的是 useEffectuseLayoutEffect

遍历逻辑如下图所示

图中画绿色勾的都会被遍历,红色勾是遍历的顺序

以上就是一文掌握React 组件树遍历技巧的详细内容,更多关于React 组件树遍历的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

一文掌握React 组件树遍历技巧

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

一文掌握React 组件树遍历技巧

这篇文章主要为大家介绍了React 组件树遍历技巧的掌握,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-16

怎么掌握React组件树遍历技巧

这篇文章主要介绍“怎么掌握React组件树遍历技巧”,在日常操作中,相信很多人在怎么掌握React组件树遍历技巧问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么掌握React组件树遍历技巧”的疑惑有所帮助!
2023-07-06

编程热搜

目录