javascript - React、单页应用程序和浏览器的后退按钮
问题描述
我知道我的问题可能只是“这无法完成,这定义了 SPA 的目的”。但...
mydomain.com
我在我的 REACT 网络应用程序中导航到。此页面从后端加载数据并填充精细的网格。加载和渲染大约需要 2 秒。
现在,我单击该详细页面上的链接并导航到mydomain.com/otherPage
. 当我单击浏览器的 BACK 按钮返回到 时mydomain.com
,它是空白的,并且必须从头开始重建,因为 SPA 规定必须在每次页面更改时擦除和重建 DOM(至少是页面特定的动态部分,如路线可以在页眉/页脚等的固定布局内)。我明白了...
除了迁移到 nextJS 和使用 SSR....
REACT 中是否有任何神奇的解决方案可以在导航出页面时以某种方式“保留”页面的 DOM,以便当您浏览器返回该页面时,该页面会立即显示而不是从头开始呈现?
解决方案
是的,在保持 DOM 呈现但隐藏的同时切换路由是很有可能的!如果您正在构建一个 SPA,那么使用客户端路由是一个好主意。这使您的任务变得简单:
要隐藏,同时将组件保留在 DOM 中,请使用以下任一 css:
.hidden { visibility: hidden }
仅隐藏未使用的组件/路由,但仍保留其布局。.no-display { display: none }
隐藏未使用的组件/路由,包括其布局。
对于路由,使用react-router-dom
,您可以在组件上使用函数 children propRoute
:
孩子们:功能
有时您需要渲染路径是否与位置匹配。在这些情况下,您可以使用功能 children 道具。它的工作原理与render 完全一样,只是无论是否匹配都会被调用。children 渲染道具接收与组件和渲染方法相同的所有路由道具,除非当路由无法匹配 URL 时,匹配为空。这允许您根据路由是否匹配来动态调整 UI。
在我们的例子中,如果路由不匹配,我将添加隐藏的 css 类:
应用程序.tsx:
export default function App() {
return (
<div className="App">
<Router>
<HiddenRoutes hiddenClass="hidden" />
<HiddenRoutes hiddenClass="no-display" />
</Router>
</div>
);
}
const HiddenRoutes: FC<{ hiddenClass: string }> = ({ hiddenClass }) => {
return (
<div>
<nav>
<NavLink to="/1">to 1</NavLink>
<NavLink to="/2">to 2</NavLink>
<NavLink to="/3">to 3</NavLink>
</nav>
<ol>
<Route
path="/1"
children={({ match }) => (
<li className={!!match ? "" : hiddenClass}>item 1</li>
)}
/>
<Route
path="/2"
children={({ match }) => (
<li className={!!match ? "" : hiddenClass}>item 2</li>
)}
/>
<Route
path="/3"
children={({ match }) => (
<li className={!!match ? "" : hiddenClass}>item 3</li>
)}
/>
</ol>
</div>
);
};
样式.css:
.hidden {
visibility: hidden;
}
.no-display {
display: none;
}
工作 CodeSandbox:https ://codesandbox.io/s/hidden-routes-4mp6c?file=/src/App.tsx
比较visibility: hidden
vs.的不同行为display: none
。
请注意,在这两种情况下,所有组件仍然安装到 DOM!您可以使用浏览器开发工具中的检查工具进行验证。
可重复使用的解决方案
对于可重用的解决方案,您可以创建可重用的HiddenRoute组件。
在下面的示例中,我使用了 hook useRouteMatch
,类似于children
Route 道具的工作方式。基于匹配,我为新组件子项提供隐藏类:
import "./styles.css";
import {
BrowserRouter as Router,
NavLink,
useRouteMatch,
RouteProps
} from "react-router-dom";
// Reusable components that keeps it's children in the DOM
const HiddenRoute = (props: RouteProps) => {
const match = useRouteMatch(props);
return <span className={match ? "" : "no-display"}>{props.children}</span>;
};
export default function App() {
return (
<div className="App">
<Router>
<nav>
<NavLink to="/1">to 1</NavLink>
<NavLink to="/2">to 2</NavLink>
<NavLink to="/3">to 3</NavLink>
</nav>
<ol>
<HiddenRoute path="/1">
<li>item 1</li>
</HiddenRoute>
<HiddenRoute path="/2">
<li>item 2</li>
</HiddenRoute>
<HiddenRoute path="/3">
<li>item 3</li>
</HiddenRoute>
</ol>
</Router>
</div>
);
}
可重用解决方案的工作 CodeSandbox:https ://codesandbox.io/s/hidden-routes-2-3v22n?file=/src/App.tsx
推荐阅读
- php - 从数组或对象在 php 中生成 CSV
- c++ - 如何在 matlab 上修复(使用 mexOpenCV 时出错)?
- amazon-web-services - 如何启动具有从列表中选择的多个 SG 的实例
- yocto - yocto krogoth 上的 hostapd
- elasticsearch - Elasticsearch计数数组中的元素,用于具有值的属性
- text - 容错文本搜索?
- swift - 无法向菜单项添加操作
- javascript - 在弹性搜索中聚合对象数组
- java - 为什么这里的 BufferedWriter 不写入文件,即使我最后关闭它?
- bash - bash 中的嵌套字典