有条件的渲染标记(JSX)与CSS`display:none`-哪种更好的做法?

时间:2019-05-20 23:45:57

标签: javascript css reactjs

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

在这种情况下,当视口小于或等于某个宽度或断点(对于本示例768px)时,我想在另一个视口上方显示一个视口。

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

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调整大小的侦听器(尽管我找不到可靠的建议来源)一个)。

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

2 个答案:

答案 0 :(得分:2)

第二种解决方案#2与解决方案#1相比非常好。因为#1在DOM对象中具有不必要的元素和不需要的元素,这也使反应混乱。尽管这也不是其他任何语言的好习惯。但是在#2中,您不会呈现不需要的内容,这将改善代码的平稳运行,并且使用这种方法进行调试和设计也很容易。

答案 1 :(得分:1)

即使涉及到更多的代码行,也绝对是第二个,整体性能结果要好得多,因为您不必在页面的各处随意放置多余的DOM元素。 更重要的是解决方案2提供的灵活性,如果将来您必须在不同的屏幕上更改基础标记,该怎么办? (例如,在较小的屏幕中隐藏一些列)