原文imkev.dev/react-route… 由石欣翻译
React Router 和嵌套路由
在 Remix v1 公开发布后,嵌套路由成为了所有人都在谈论的话题,至少在我所处的互联网世界的小角落里是这样。但是什么是嵌套路由,它们为什么重要,以及如何在您的 React 应用程序中使用嵌套路由?
React Router
嵌套路由从很早就存在于 React Router 中,它最初被命名为 react-nested-router 。现在在版本 6 上,React Router 是最受欢迎的 React 包之一,在整篇文章中 React Router 也将用于演示嵌套路由的概念。包括 React Router v5 代码示例和演示,但在解释代码时,请参考 v6 版本。
## Nested routes
嵌套路由是页面布局中响应路由更改的区域。例如,在单页应用程序中,从一个 URL 导航到另一个 URL 时,不需要呈现整个页面,而只需呈现页面中依赖于该 URL 更改的那些区域。
在上面的线框中,当单击标题链接 (4) 时,将呈现主要内容 (1) 以显示此路由的内容,而标题保持不变。同样,当单击左侧导航链接 (2) 时,页面的内容部分 (3) 将更新以显示新内容,但页眉、页脚和导航菜单保持不变。
此布局可以通过多种方式实现。
export default function App() {
return (
<div className="app">
<BrowserRouter>
<Routes>
<Route path="/catalog/:id" element={<Catalog />} />
<Route path="/catalog" element={<Catalog />} />
<Route path="/welcome" element={<Welcome />} />
<Route index element={<Home />} />
</Routes>
</BrowserRouter>
</div>
);
}
Flat ro平面路由结构 - v6 | 平面路由结构 - v5
在上面的平面结构中,我们在单个文件中声明了四个路由。 /catalog/:id 和 /catalog 将呈现包含左侧导航和内容区域的 组件。如果存在 :id 参数,则它将显示该 :id 的内容,否则将显示一些默认内容。 /welcome 显示欢迎消息,最终捕获全部路由显示主页,包括 <Header>
和 <Footer>
。
在不同路线之间导航将导致主部分 (1) 使用更新的内容呈现。这包括 <Header>
、 <Footer>
和 <Nav>
- 即使它们没有更改。如果你使用过这个演示,你可能会觉得它运行良好,没有明显的错误。这种路由结构相当普遍,我个人在生产中多次遇到过它。但是,这种结构没有经过优化,当从一个 URL 导航到另一个 URL 时,CPU 正在做很多不需要的工作。在我们的示例中,这种开销可以忽略不计,但在更复杂的应用程序中,它可能会导致可见的卡顿并恶化用户体验。
为了使重新渲染更加明显,添加了以下代码片段,但最初将其注释掉。
React.useLayoutEffect(() => {
if (ref && ref.current) {
ref.current.style = "background-color: #fa9a9a;";
setTimeout(() => {
ref.current.style = "background-color: none;";
});
}
});
lets-get-nested
可以使用嵌套路由来优化上述路由结构,以避免呈现未更改的组件。作为默认规则,我们只想渲染已更改的内容。当用户单击左侧导航链接时,我们唯一要呈现的组件是内容部分。同样,当用户单击标题链接时,我们只呈现主要部分。
export default function App() {
return (
<div className="app">
<BrowserRouter>
<Routes>
<Route path="/welcome" element={<Welcome />} />
<Route path="*" element={
<Header />
<Routes>
<Route path="/catalog/*" element={
<div className="two-column" ref={ref}>
<Nav />
<div className="content">
<Routes>
<Route path=":id" element={<Content />} />
<Route
index
element={<p>Use the left nav to selet a catalog item</p>}
/>
</Routes>
</div>
</div>
} />
<Route index element={<Home />} />
</Routes>
<Footer />
} />
</Routes>
</BrowserRouter>
</div>
);
}
我们现在有六条路线分布在三个级别上,而不是在一个级别上有三条路线。在最顶层,我们有两个路由, path="*" 和 path="/welcome" 。这两个路由是分开的,因为
和 在 页面上不可见。在第二级,我们有两个路由, path="/catalog/" 和 index 。它们分别用于呈现 或 。正如您在上面的代码片段中看到的,
和 包含在 path="" 的 element 属性中,而不是像我们在平面结构中所做的那样在 和 中声明。最后,在最里面的一层,还有两条路线。第一个路径使用 path=":id" 公开 :id 参数。由于此路由是 path="/catalog/*" 的嵌套路由,因此该路径构建在其父路径上,在 /catalog/:id 中匹配。当不存在 :id 时,将使用 index 路由。
尝试演示,就看到每个组件仅在需要时渲染,从而使该解决方案比我们之前看到的解决方案更加优化。
嵌套路由并不是一个新概念。早在 2009 年,我们就在 C# 的 MVC 框架上使用某种形式的嵌套路由。然而,仍然有开发人员选择扁平结构的情况,而嵌套路由将是更好的解决方案。虽然嵌套路由今天可以帮助你,但预计嵌套路由在不久的将来会变得更加重要,像Island Architecture这样的概念和像Remix这样的框架会越来越受欢迎。