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,您可以在组件上使用函数 childrenRoute:
儿童:功能
有时您需要渲染路径是否与位置匹配。在这些情况下,您可以使用函数 children 道具。它的工作方式与 render 完全一样,除了无论是否匹配都会调用它。 children 渲染道具接收与组件和渲染方法相同的所有路由道具,除非路由无法匹配 URL,则 match 为空。这允许您根据路由是否匹配动态调整您的 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: hiddenvs.的不同行为display: none。
请注意,在这两种情况下,所有组件仍然挂载到 DOM!您可以使用浏览器开发工具中的检查工具进行验证。
可重复使用的解决方案
对于可重用的解决方案,您可以创建一个可重用的HiddenRoute组件。
在以下示例中,我使用 hook useRouteMatch,类似于childrenRoute 道具的工作方式。根据匹配,我为新组件子级提供隐藏类:
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