javascript React:隐藏与删除组件[已关闭]

4ioopgfo  于 2023-03-16  发布在  Java
关注(0)|答案(7)|浏览(122)

已关闭。此问题为opinion-based。当前不接受答案。
**想要改进此问题吗?**请更新此问题,以便editing this post可以用事实和引文来回答。

1年前关闭。
Improve this question
这个问题更多的是关于架构而不是编码。
在React中,有时我们想要隐藏组件。例如,当用户在SPA中打开新页面时,当一些吐司关闭时,等等。我们可以通过添加display: none来隐藏它们。或者我们可以从虚拟DOM中删除它们。

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

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

我们的一些前辈有时候会使用第一种方法,即使他们隐藏了整个页面,他们是这样说这个方法的:在这种情况下,React会预呈现所需的内容,因此当内容必须显示时,所需的时间会更少。
但是在这种情况下我们不能使用生命周期钩子,因为即使组件隐藏了,它也不会被删除。但是我认为主要的问题是,真实的的DOM变得巨大。这带来了缓慢,不是吗?
那么,什么更好呢?
我没有找到任何关于这个问题的对话。也许你可以帮助我。
编辑1:尽管事实上有一些答案,我想知道更多的意见。所以,我决定打开一个赏金

vshtjzan

vshtjzan1#

让我们比较一下这两种切换HTML元素可见性的方法之间的一些差异,元素切换(aka display: none|block)和JSX短路呈现
1.简单性-正如你所知,JSX已经针对被动切换标记进行了优化,所以它不会打印falsetruenullundefined,因此你可以在其中编写更短的逻辑。Facebook www.example.com也带来了不使用模板文字而不是JSX的类似情况https://facebook.github.io/jsx/#why-not-template-literals。简单性带来了可维护性,从长远来看,它将帮助您的应用程序不会成为另一个意大利面废话。

isShown && <div />

对比

<div style={{ display: isShown ? 'block' : 'none' }} />

1.性能-跨越更多节点对性能和内存使用率都没有好处,一般来说,每个应用程序的性能都不一样。可以使用Chrome的性能监控器或React Profiler进行基准测试。但更重要的是,React围绕着你会遵循https://reactjs.org/docs/jsx-in-depth.html而不是使用其他技巧的知识构建了新的性能优化。假设您的部分或大部分代码库使用element toggling方法,并且有一个性能改进的新版本React,那么您可能需要花费数周的时间进行重构才能从中受益。
1.错误-使用JSX短路渲染时,您必须记住不要使用elements.length && elements.map(({ text }) => text)之类的内容,因为elements数组没有成员,JSX将打印0而不是空。另一方面,使用display: block设置可见性几乎肯定会导致flexinlineinline-blocktable元素被设置为block。第二个bug更难发现,因为你需要处理css样式或css-in-js。
1.一致性-JSX短路渲染是React维护者推荐的方法,它将出现在大多数React项目中。但是如果你将它与老式的显示切换方法混合使用,任何加入团队的新开发人员都会质疑你为什么同时使用这两种方法。混合使用这些元素很可能会导致错误,其中一个元素可能由JSX显示,同时又被display: none隐藏,反之亦然。
1.调试-使用React Devtools或Elements,同时将许多元素设置为display: none,这是一场噩梦,因为它会被根本不需要的节点污染
我估计资深开发人员习惯于使用display来切换元素,因为它被认为是老派的。这也可能是将应用程序从jQuery转换为React的遗留问题。这是当时制作UI的唯一方法。有些习惯或者我应该说心理模型是相当粘滞的。现在在React项目中,我会认为上述方法是一种黑客攻击。
除了标准的JSX shortcircuit renderingisShown && <div />之外,我建议不要使用任何其他方式来切换React中标记的可见性。在我编写React应用程序的长期经验中,我试图坚持使用最简单和最具表达力的代码,所有开发人员从大学毕业生到大三学生,再到大四学生都希望按照最佳实践,并且不会有阅读困难。因此它们重用而不是编写相同组件的第n个版本。
编辑:正如在其他答案中提到的,过渡动画通常是用React-过渡-组包完成的,它只适用于JSX短路渲染。

laik7k3q

laik7k3q2#

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

靶区;DR

您需要牢记以下几点,才能根据您的特定使用情形做出***自己的***决定:

  • 在构建呈现树时,隐藏的DOM元素会被忽略,因此通过样式控制可见性时,您可能看到的唯一性能提升可能是由于提前构建DOM树而导致的。
  • 当可见性由样式设置控制时,多余的DOM大小may slow down your browser是不必要的。
  • 另一方面,从React的Angular 来看,应用条件渲染(并重建后代树,一旦您决定使它们可见)似乎比更改单个属性稍微昂贵一些。

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

***p.s:***除了您可能关心的性能之外

  • SEO -如果您有条件地渲染一些导航面板/对话框,其中包含指向应用其他页面的链接,这些链接将不会出现在您的DOM中,因此无法被爬虫遍历和索引,如果您使用样式设置切换可见性,则不会出现这种情况;
  • 用户体验-如果根据设计,UI元素必须在屏幕上显示/消失动画(例如淡入/淡出),如果您使用条件渲染,您可能需要更多advanced techniques以确保动画仍然有效,不会让您的用户感到沮丧
  • 可访问性-使用display: none从视图中隐藏的UI部分仍可由屏幕阅读器访问
sqougxex

sqougxex3#

∮一些事实∮

  • 代码到像素是一个多步骤的过程,一般认为javascript需要10- 12 ms来维持60 fps。
  • 过早的优化是一个坏主意,所以测量-〉优化-〉测量-〉重复。

简短的答案是depends。一些可能的情景。

正在获取(API、img、视频)

  • 通常甚至在用户访问页面之前就结束了获取。
  • 例如,下面的img甚至会在用户访问页面之前被获取,任何API请求也是如此。
<div style={{ display: "none" }}>
        <img src="https://picsum.photos/200/300" />
      </div>
  • 因此,如果你是API重或图像重注意到这一点。有一种方法来防止这种行为,但不可能在秩序的版本。
  • 此外,如果Assert是预渲染的唯一原因,则可以基于优先级执行prefetch asserts

动画

  • 这已经被发布过很多次了,但是有一个简单而优雅的解决方案。在实际的组件周围写一个 Package 器(最好是HOC),让它同时为一个空的div显示none,并为实际的组件条件渲染。所以如果你想动画繁荣,你是很好的去。

性能

  • 在代码到像素的转换中,JS需要花费大量的时间,尤其是在代码第一次运行时。
  • 因此,如果您使用display none属性执行cat page JS,而用户希望看到dog page,那么祝您好运,可以留住用户。
  • 另一方面,如果你成功地做了很少或没有性能损失,请张贴您的方法,我很乐意阅读它。
  • 理想情况下,您可以使用SSR预取HTML来解决这个问题,因为它只会刷新RAW HTML,用户只需要在浏览器中呈现它,这相当于更改显示属性。
  • 另一方面,如果您只是使用它来呈现一些静态页面,更改display属性可能是可以的,但首先为什么要使用react是有争议的。

因此,从一般意义上讲,我个人更喜欢有条件的渲染,除非访问整个页面的几率像@Yevgen Gorbunkov所说的那样高。

fjnneemd

fjnneemd4#

如果你想使用生命周期,也有一些变通方法。如果你使用功能组件,那么你可以使用依赖属性来管理重渲染。
如果你过度使用https://web.dev/dom-size/,它的真实dom大小会降低你的速度,但是如果那些组件不断更新,而不是根据需要渲染一个新组件,它会更好。
如果它是一个项目列表,而且数量巨大,我建议您查看https://react-window.vercel.app/#/examples/list/fixed-size或https://bvaughn.github.io/react-virtualized/#/components/List

b1payxdu

b1payxdu5#

就我个人而言,我更喜欢删除,但这样可以防止动画淡出。我喜欢使用这样的东西来获得两者的好处。

const FadeContainer = ({ show: showProp, children }) => {
  const [show, setShow] = useState(showProp);
  const timeoutRef = useRef();

  useEffect(() => {
    if (showProp) {
      setShow(true);
    } else {
      timeoutRef.current = setTimeout(() => setShow(false), 500);
    }
    return () => clearTimeout(timeoutRef.current);
  }, [showProp])

  return show && (
    <div style={{ opacity: showProp ? 1 : 0, transition: "opacity 0.5s ease" }}>
      {children}
    </div>
  );
}
jrcvhitl

jrcvhitl6#

“这要看情况”是对很多问题的回答。
这种讨论也出现在我所在的前端团队中。随着时间的推移,有几件事被考虑在内。
使用React,路由主要在客户端处理,这在如何处理组件和页面的呈现方面为您提供了极大的灵活性。
你工作的网站是否有一个很大的登陆页面,也许只有很少的小页面?那么我怀疑最初获取并加载到DOM中的额外DOM元素和HTML文件大小几乎没有影响。通过样式使它们不可见是完全可以的。
网站是否有很多页面,访问者是否不太可能访问其中的绝大多数?那么用css隐藏所有额外的DOM元素会有很多缺点。想想初始加载时间,需要获取的资产会显著增长。在这种情况下,为不同的路径实现代码分割可能是一个好主意,使隐藏元素不再是一个选项。
中间地带也是很有可能的,根据你网站的(子)路径进行代码分割是有意义的,但是使用css来隐藏模态元素,鼠标悬停时弹出的元素,等等,这样页面中的所有内容都是敏捷的。
就像在其他答案中提到的,使用一个 prop 来设置可见性是一个很好的方法,可以让淡入**和淡出(当然这更难)**成为可能。Samuels answer是一个很好的建议。另外,我的团队使用React Transition Group来设置基于转换状态的类,允许元素的动画化,以及如果你愿意的话从DOM中删除组件。
我认为这是一个有趣的问题,希望能听到更多的意见,从其他人了。

x7yiwoj4

x7yiwoj47#

我认为两者都有优点和缺点。
请参阅本文。Compare the performance between hiding React components with css and state management
使用显示CSS属性隐藏组件将更快地切换显示和隐藏。使用非CSS方式删除组件,当条件状态值为false时,它将减少一个需要重新呈现的组件,从而提高性能。
哪个更好取决于您对项目的选择。

相关问题