【发布时间】: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