React:隐藏与删除组件

IT技术 javascript reactjs dom
2021-05-22 18:47:49

这个问题是关于架构而不是编码。

这是这种情况。在 React 中,有时我们想隐藏组件。例如,当用户在 SPA 中打开新页面时,当某些 Toast 关闭时等。我们可以通过添加display: none. 或者我们可以将它们从虚拟 DOM 中移除。

// Hidden div
<div style={{ display: 'none' }}/>

// Removed div
{false && <div/>}

然后我们的一些老年人使用第一种变体。即使他们隐藏了整个页面。这就是他们对这种方法的看法:“这种情况下 React 会预渲染所需的内容,因此当内容必须出现时,它花费的时间更少”。

但是在这种情况下我们不能使用生命周期钩子,因为即使组件隐藏,它也不会被移除。但我认为的主要问题是真正的 DOM 变得巨大。这会带来缓慢,不是吗?

那么,什么更好?


我没有找到关于这个问题的任何对话。也许你可以帮助我。


编辑 1:尽管有一些答案,但我想知道更多的意见。所以,我决定开放赏金

4个回答

让我们比较一下这两种切换 HTML 元素可见性、元素切换(又名display: none|block)和JSX 短路渲染的方法之间的一些差异

  1. 简单-你知道JSX已经为被动触发的标记,所以它不会打印进行优化falsetruenullundefined,因此你可以在里面写短逻辑。Facebook https://facebook.github.io/jsx/#why-not-template-literals提出了类似的不使用模板文字而不是 JSX 的案例简单导致可维护性,从长远来看,它将帮助您的应用程序不会成为另一个意大利面条式的废话。
  isShown && <div />

对比

 <div style={{ display: isShown ? 'block' : 'none' }} />
  1. 性能- 跨越更多节点的方式对于性能和内存使用来说永远不会有好处,通常它会因应用程序而异。可以使用 Chrome 的性能监视器或 React Profiler 对其进行基准测试。但更重要的是,React 围绕您将遵循https://reactjs.org/docs/jsx-in-depth.html而不是使用其他技巧的知识构建新的性能优化鉴于您的部分或大部分代码库正在使用该element toggling方法,并且有一个具有性能改进的新版本 React,您可能需要花费数周时间进行重构以从中受益。

  2. 错误- 使用 JSX 短路渲染时,您必须记住不要使用类似的东西elements.length && elements.map(({ text }) => text),因为elements数组没有成员,JSX 将打印 0 而不是什么。在与对方设置的知名度display: block几乎肯定会导致flexinlineinline-blocktable元素被设置为block第二个错误更难发现,因为您需要处理 css 样式或 css-in-js。

  3. 一致性- 鉴于 JSX 短路渲染是 React 维护者推荐的方法,它将出现在大多数 React 项目中。但是如果你把它和老式的显示切换方法混合在一起,任何新加入团队的开发人员都会质疑你为什么同时使用这两种方法。混合这些很可能会导致错误,其中一个元素可能会被 JSX 显示,同时被隐藏,display: none反之亦然。

  4. 调试- 使用 React Devtools 或 Elements 同时设置大量元素display: none是一场噩梦,因为它会被您根本不需要的节点污染

我认为高级开发人员习惯于切换元素,display因为它被认为是老派。这也可能是将您的应用程序从 jQuery 转换为 React 的inheritance。这是当时制作 UI 的唯一方法。一些习惯或者我应该说心智模型非常粘。现在在 React 项目中,我会认为上述是一个 hack。

我建议不要使用任何其他方式来切换 React 中标记的可见性,而是使用标准的JSX 短路渲染 isShown && <div />在我编写 React 应用程序的长期经验中,我试图坚持最简单和最具表现力的代码,所有开发人员从大学毕业生到大三到大四的人都会按照最佳实践期望并且不会有阅读困难,所以他们更愿意重用而不是编写同一组件的第 n 个版本。

编辑:正如在其他答案中提到的,过渡动画通常使用 react-transition-group 包完成,该包仅适用于 JSX 短路渲染。

注意:对于那些对冗长的解释不感兴趣(试图获得代表赏金),然后是不相关的例子和阴谋的人,这里有一个快速的解释

TL; 博士

您需要牢记以下几点才能做出自己的决定,具体取决于您的特定用例:

  • 在构建渲染树时会忽略隐藏的 DOM 元素,因此您可能会看到的唯一性能提升可能是由于提前构建 DOM 树造成的。

  • 过大的 DOM可能会不必要地降低浏览器的速度

  • 从 React 的角度来看,应用条件渲染(并重建后代树,一旦你决定让它们可见)似乎比改变单个属性稍微贵一些。

考虑到上述情况,对于被访问(或在用户交互过程中大部分时间都显示)的复杂组件(大型 DOM 子树),切换可见性样式是有意义的。否则,从性能的角度来看,条件渲染似乎是更好的选择。

一些事实

简短的回答depends一些可能的场景。

获取(API,img,视频)

  • 通常甚至在用户访问页面之前就结束了获取。
  • 例如,即使在用户访问页面之前,下面的 img 也会被获取,对于任何 API 请求也是如此。
     <div style={{ display: "none" }}>
        <img src="https://picsum.photos/200/300" />
      </div>
  • 因此,如果您使用 API 重或图像重,请注意它。有一种方法可以防止这种行为,但在 order 版本中是不可能的。
  • 此外,如果断言是您预渲染的唯一原因,您可以根据优先级预取断言

animation

  • 它已经被多次发布,但有一个简单而优雅的解决方案。在实际组件周围编写一个包装器(首选 HOC),并让它为空 div 显示 none 和实际组件的条件渲染。因此,如果您想为热潮设置动画,那么您就可以开始了。

表现

  • 在代码到像素的转换中,JS 需要花费大量时间,尤其是第一次运行代码时。参考 JS 引擎内部结构从这里开始
  • 因此,如果您执行带有 display none 属性的 cat page JS,而用户希望看到 dog page 祝您好运留住用户。
  • 另一方面,如果您在性能下降较少或没有性能下降的情况下取得了成功,请发布您的方法,我很乐意阅读它。
  • 理想情况下,您也可以使用 SSR 和预取 HTML 来解决这个问题,因为它只是刷新 RAW HTML 用户只需要在浏览器中呈现它,这相当于更改显示属性。
  • 另一方面,如果你只是用它来渲染一些静态页面,改变显示属性可能没问题,但首先为什么要争论react

所以总的来说,我个人更喜欢有条件的渲染,除非访问整个页面的几率很高,如@Yevgen Gorbunkov所说。

好吧,如果您想使用生命周期,那么也有解决方法。如果您正在使用功能组件,那么您可以使用依赖props管理重新渲染。

如果您过度使用它,它的真实 dom 大小会减慢您的速度https://web.dev/dom-size/ 但如果这些组件不断更新而不是按需呈现新组件,则效果会更好。

如果它是一个项目列表和它的巨大我建议你看看https://react-window.vercel.app/#/examples/list/fixed-sizehttps://bvaughn.github.io/react -虚拟化/#/components/List