【问题标题】:Conditionally Rendering Markup (JSX) vs. CSS `display: none` - Which is better practice?条件渲染标记 (JSX) 与 CSS `display: none` - 哪个更好?
【发布时间】:2019-10-07 08:24:54
【问题描述】:

假设我有一个内容相同的组件,但根据设备(桌面视口或移动视口)呈现两种完全不同的标记结构。

在这种情况下,当视口低于或高于某个宽度或断点(本例为768px)时,我想将一个显示在另一个之上。

类似情况的常见情况可能是导航,在桌面视图中,您在页面标题中有一个简单的导航栏,而在移动视图中,您有一个更复杂的导航菜单,可以滑入和滑出:

import React from 'react';
import './Navigation.scss';

const Navigation = () => {
  return (
    <div className="navigation">
      <div className="mobile-navigation-container">
        <MobileNavigation />
      </div>
      <div className="desktop-navigation-container">
        <DesktopNavigation />
      </div>
    </div>
  );
};

解决方案 1:

一个简单的解决方案是使用 CSS:

.navigation {
  .mobile-navigation-container {
    @media (min-width: 768px){
      display: none;
    }
  }
  .desktop-navigation-container {
    @media (max-width: 767px){
      display: none;
    }
  }
}

但是,这里的问题是我在 DOM 中仍然有两个视图,即使一个不可见。

解决方案 #2:

或者,我可以在我的 JSX 组件中使用调整大小侦听器和状态片段,根据我可以使用 window.innerWidth 计算的视口宽度有条件地渲染正确的组件:

import React, { Component } from 'react';
const isClient = typeof window !== 'undefined';

class Navigation extends Component {
  state = {
    viewportWidth: 0,
  }

  componentDidMount() {
    if (isClient) {
      this.updateWindowDimensions();
      window.addEventListener('resize', this.updateWindowDimensions);
    }
  }

  componentWillUnmount() {
    if (isClient) window.removeEventListener('resize', this.updateWindowDimensions);
  }

  updateWindowDimensions = () => {
    this.setState({ viewportWidth: window.innerWidth });
  }

  render() {
    const { viewportWidth } = this.state;
    return (
      <div className="navigation">
        {viewportWidth <= 768 && (
          <div className="mobile-navigation-container">
            <MobileNavigation />
          </div>
        )}
        {viewportWidth > 768 && (
          <div className="desktop-navigation-container">
            <DesktopNavigation />
          </div>
        )}
      </div>
    );
  }

这解决了 DOM 上有重复内容的问题。我猜这对搜索引擎爬虫来说更好。

然而,这在某种程度上使我的 JSX 更加复杂,我觉得 CSS 断点在性能方面更干净、更流畅的实现,而不是使用 JavaScript 调整大小监听器(尽管我找不到可靠的资源来建议一个接一个)。

我的问题是这两种实现中哪一种更好,为什么?

【问题讨论】:

  • 来自Vue docs,但关于相同的问题:“一般来说,v-if [条件渲染] 具有更高的切换成本,而v-show [css 隐藏] 具有更高的初始渲染成本。所以更喜欢v-show [css hidden] 如果你需要经常切换某些东西,如果条件不太可能在运行时改变,则更喜欢v-if [conditional rendering]。”由于切换设备中间视图的可能性不大......

标签: javascript css reactjs


【解决方案1】:

绝对是第二个,尽管它涉及更多的代码行,但整体性能结果要好得多,因为您没有多余的 DOM 元素在页面中到处乱放。 更重要的是方案 2 提供的灵活性,如果将来必须更改不同屏幕上的底层标记怎么办? (例如,在小屏幕中隐藏一些列)

【讨论】:

    【解决方案2】:

    与解决方案#1 相比,第二种方法解决方案#2 非常好。因为#1 在 DOM 对象中有不必要和不需要的元素,这也让反应感到困惑。尽管这在任何其他语言中也不是一个好习惯。但是在 #2 中,您不会渲染不需要的内容,这将提高代码的流畅运行,并且在这种方法中调试和设计也很容易。

    【讨论】:

      猜你喜欢
      • 2017-08-22
      • 2020-10-12
      • 1970-01-01
      • 2018-10-16
      • 2018-06-30
      • 2021-10-11
      • 1970-01-01
      • 2016-01-02
      • 2017-03-08
      相关资源
      最近更新 更多