假设我有一个内容相同的组件,但根据设备(桌面视口(viewport)或移动视口(viewport))呈现了两种完全不同的标记结构。
在这种情况下,当视口(viewport)低于或高于特定宽度或断点(对于本例 768px
)时,我想在另一个之上显示一个。
这种情况的常见情况可能是导航,在桌面 View 中,您在页面标题中有一个简单的导航栏,而在移动 View 中,您有一个更复杂的导航菜单,可以滑入和滑出:
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>
);
};
解决方案一:
一个简单的解决方案是使用 CSS:
.navigation {
.mobile-navigation-container {
@media (min-width: 768px){
display: none;
}
}
.desktop-navigation-container {
@media (max-width: 767px){
display: none;
}
}
}
但是,这里的问题是我在 DOM 中仍然有两个 View ,即使一个 View 不可见。
解决方案#2:
或者,我可以在我的 JSX 组件中使用调整大小的监听器和状态片段,根据我可以使用 window.innerWidth
计算的视口(viewport)宽度有条件地呈现正确的组件:
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 调整大小监听器更清晰、更流畅的实现(尽管我找不到可靠的来源来建议一个在另一个之上)。
我的问题是这两种实现方式中哪一种更好,为什么?
最佳答案
与解决方案 #1 相比,第二种方法解决方案 #2 非常好。因为 #1 在 DOM 对象中有不必要的和不需要的元素,这也让 React 感到困惑。尽管这在任何其他语言中也不是一个好习惯。但在 #2 中,您不会渲染不需要的内容,这将提高代码的流畅运行,并且调试和设计在这种方法中也很容易。
关于javascript - 条件渲染标记 (JSX) 与 CSS `display: none` - 哪个更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56229860/