我正在阅读React路由器中的static vs dynamic routing,并且我正努力找出后者的优势(以及为什么v4选择使用它)。我可以看到列出应用程序的所有路由(静态)的优势,以及每个路由映射到的组件,允许您跟踪给定特定URL的内容。但我没有看到动态路线有任何明显的优势。
如果有的话,我只能看到缺点,因为没有明确的方法来查看URL将映射到哪个状态,而无需从根应用程序元素开始并按照路径进行操作(尽管我可能会弄错)。
动态路由会解决什么情况?为什么它更适合静态路由(可能特别是在React应用程序中)?
答案 0 :(得分:12)
来自反应路由器docs:
当我们说动态路由时,我们指的是路由作为您的 app正在呈现,而不是在a之外的配置或约定中 正在运行的应用程序。
早期版本的react-router
(v4之前版本)曾经有过静态路由。这导致
在以下应用中集中路由:
<Router>
<Route path='/' component={Main}>
<IndexRoute component={Home} />
<Route path='about' component={About} />
<Route onEnter={verifyUser} path='profile' component={Profile} />
...
</Route>
</Router>
然而,这并不完全是 React方式的做法。 React专注于使用基于组件的逻辑的组合。因此,我们可以将它们想象为静态系统,而不是将它们想象为静态系统,而是将它们视为组件,这就是路由器v4带来的反应以及它背后的主要理念。
因此,我们可以使用Route
,因为我们会使用任何React组件。这使我们可以在构建不同组件时添加Route
组件。这样做的一个好处是我们可以将路由逻辑解耦到需要它们的组件。
About
组件可以处理所有路线,并根据网址有条件地呈现部分UI(例如/about/job
或/about/life
等)。
需要注意的另一件事是Route
组件将为匹配的路由呈现组件或null
。例如,以下Route
会为路由About
和/about
(或者没有)呈现null
组件。
<Route path='about' component={About} />
这也类似于我们习惯于在React中有条件地渲染组件:
route === '/about' ? <About /> : null
现在,如果我们需要在About
组件中为路由/about/job
或/about/life
呈现一些其他组件,我们可以这样做:
const About = ({ match ) => (
<div>
...
<Route path={`${match.url}/job`} component={Job} />
<Route path={`${match.url}/life`} component={Life} />
</div>
)
我个人也发现,如果我使用动态导入和代码分割,这种方法对我来说效果更好,因为我可以在任何组件中添加动态路由。例如,
import Loadable from 'react-loadable';
const Loading = () => (
<div />
);
const Job = Loadable({
loader: () => import('./Job'),
loading: Loading,
});
const Life = Loadable({
loader: () => import('./Life'),
loading: Loading,
});
...
render() {
return (
...
<Route path={`${match.url}/job`} component={Job} />
<Route path={`${match.url}/life`} component={Life} />
)
}
动态路由的另一个很好的用例是创建响应式路由,这些路由在react router docs中得到了很好的解释和推荐的读取。以下是文档中的示例:
const App = () => (
<AppLayout>
<Route path="/invoices" component={Invoices}/>
</AppLayout>
)
const Invoices = () => (
<Layout>
{/* always show the nav */}
<InvoicesNav/>
<Media query={PRETTY_SMALL}>
{screenIsSmall => screenIsSmall
// small screen has no redirect
? <Switch>
<Route exact path="/invoices/dashboard" component={Dashboard}/>
<Route path="/invoices/:id" component={Invoice}/>
</Switch>
// large screen does!
: <Switch>
<Route exact path="/invoices/dashboard" component={Dashboard}/>
<Route path="/invoices/:id" component={Invoice}/>
<Redirect from="/invoices" to="/invoices/dashboard"/>
</Switch>
}
</Media>
</Layout>
)
总结docs,您会注意到使用动态路由将Redirect
添加到大屏幕尺寸变得多么简单和声明。在这种情况下使用静态路由将非常麻烦,并且需要我们将所有路由放在一个地方。动态路由简化了这个问题,因为现在逻辑变得可组合(如组件)。
有些问题无法通过动态路由轻松解决。 static routing的一个优点是它允许在渲染之前检查和匹配路由。因此,它在服务器端尤其有用。反应路由器团队还在开发一个名为react-router-config的解决方案,引用该解决方案:
随着React Router v4的推出,不再有了 集中路由配置。它有一些用例 了解所有应用程序的潜在路线很有价值,例如:
- 在呈现下一个屏幕之前在服务器上或生命周期中加载数据
- 按名称链接到路线
- 静态分析
醇>
希望这提供了动态路由和静态路由及其用例的良好总结:)
答案 1 :(得分:4)
根据React-Router文档:
当我们说动态路由时,我们指的是作为您的路由发生的路由 app正在呈现,而不是在a之外的配置或约定中 运行应用程序这意味着几乎所有东西都是React中的一个组件 路由器。
明确的解释是,所有路由都没有在应用程序开始时初始化,
在 React-router v3 或更低版本中,它使用静态路由,所有路由都将在顶层初始化,并且嵌套过去就像
<Router>
<Route path='/' component={App}>
<IndexRoute component={Dashboard} />
<Route path='users' component={Users}>
<IndexRoute component={Home}/>
<Route path="users/:id" component={User}/>
</Route>
</Route>
</Router>
通过这个API设置,react-router重新实现了React的部分(生命周期等),并且它与React建议使用的组合逻辑不匹配。
使用动态路线可以预见以下优点
嵌套路线
具有动态路由的嵌套路由更像是
const App = () => (
<BrowserRouter>
{/* here's a div */}
<div>
{/* here's a Route */}
<Route path="/todos" component={Todos}/>
</div>
</BrowserRouter>
)
// when the url matches `/todos` this component renders
const Todos = ({ match }) => (
// here's a nested div
<div>
{/* here's a nested Route,
match.url helps us make a relative path */}
<Route
path={`${match.path}/:id`}
component={Todo}
/>
</div>
)
在上面的示例中,仅当/ todos与route-path匹配时,才会挂载Todo组件,然后才会定义Route路径/todos/:id
。
响应路线
React-router docs有一个很好的用例。
考虑用户导航到/invoices
。您的应用适用于不同的屏幕尺寸,它们具有较窄的视口,因此您只需向其显示发票列表和发票dashboard
的链接。他们可以从那里深入导航。
然而,在大屏幕上,导航位于左侧,仪表板或特定发票显示在右侧。
因此/invoices
不是大屏幕的有效路线,我们希望重定向到/invoices/dashboard
。这可能发生,用户将他/她的手机从portait to a landscape mode
旋转。这可以使用动态路由
const Invoices = () => (
<Layout>
{/* always show the nav */}
<InvoicesNav/>
<Media query={PRETTY_SMALL}>
{screenIsSmall => screenIsSmall
// small screen has no redirect
? <Switch>
<Route exact path="/invoices/dashboard" component={Dashboard}/>
<Route path="/invoices/:id" component={Invoice}/>
</Switch>
// large screen does!
: <Switch>
<Route exact path="/invoices/dashboard" component={Dashboard}/>
<Route path="/invoices/:id" component={Invoice}/>
<Redirect from="/invoices" to="/invoices/dashboard"/>
</Switch>
}
</Media>
</Layout>
)
将动态路由与React Router一起使用,请考虑components
,而不是静态路由。
代码拆分
网络的一个重要特点是我们不必让访问者在使用之前下载整个应用程序。您可以将代码拆分视为逐步下载应用程序。 This is made possible with Dynamic Routing
。
它带来的好处是不需要立即下载所有代码,因此可以使初始渲染更快。
Here 是一篇很好的文章,可以帮助您为应用程序设置代码分割
编写可合成的经过身份验证的路由
使用动态路由,它也更容易编写PrivateRoutes(进行身份验证的HOC),允许对用户进行身份验证并为他们提供对特定路由的访问权限,否则将重定向。这个叫我所有人都非常一般地
典型的私人路线看起来像
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
可以用作
<PrivateRoute path="/protected" component={Protected} />