React中动态与静态路由的优点

And*_*sov 20 reactjs react-router react-router-v4 dynamic-routing

我正在阅读React路由器中的静态与动态路由,我正在努力识别后者的优势(以及为什么v4选择使用它).我可以看到列出应用程序的所有路由(静态)的优势,以及每个路由映射到的组件,允许您跟踪给定特定URL的内容.但我没有看到动态路线有任何明显的优势.

如果有的话,我只能看到缺点,因为没有明确的方法来查看URL将映射到什么状态,而无需从根应用程序元素开始并按照路径进行操作(尽管我可能会弄错).

动态路由解决了什么情况?为什么它更适合静态路由(可能特别是在React应用程序中)?

Div*_*ani 12

动态路由

来自react路由器文档:

当我们说动态路由时,我们指的是在您的 应用呈现时发生的路由,而不是在正在运行的应用之外的配置或约定中.

将路线视为组件

早期版本react-router(pre v4)曾经有过静态路由.这导致了以下应用中的集中路由:

<Router>
    <Route path='/' component={Main}>
      <IndexRoute component={Home} />
      <Route path='about' component={About} />
      <Route onEnter={verifyUser} path='profile' component={Profile} />
      ...
    </Route>
</Router>
Run Code Online (Sandbox Code Playgroud)

但是,这并不是React的做事方式.React专注于使用基于组件的逻辑的组合.因此,我们可以将它们视为组件,而不是将我们的路由想象成静态系统,这就是路由器v4带来的反应以及它背后的主要理念.

因此,我们可以Route使用任何React组件.这使我们可以Route在构建不同组件时添加组件.这样做的一个好处是我们可以将路由逻辑解耦到需要它们的组件.

筑巢路线

About组件可以处理所有的路线和条件呈现根据网址(比如UI的部分/about/job/about/life等).

另一件需要注意的是,Route组件将为匹配的路径渲染组件或null.例如,以下Route呈现About对一个路径成分/aboutnull(或没有),否则.

<Route path='about' component={About} />
Run Code Online (Sandbox Code Playgroud)

这也类似于我们在React中有条件地渲染组件的方式:

route === '/about' ? <About /> : null
Run Code Online (Sandbox Code Playgroud)

现在,如果我们需要在组件内部About为路由渲染一些其他组件,/about/job或者/about/life我们可以这样做:

const About = ({ match ) => (
    <div>
        ...
        <Route path={`${match.url}/job`} component={Job} />
        <Route path={`${match.url}/life`} component={Life} />
    </div>
)
Run Code Online (Sandbox Code Playgroud)

动态导入和代码拆分

就个人而言,我也发现这种方法对我来说效果更好,以防我使用带代码分割的动态导入,因为我可以在任何组件中添加动态路由.例如,

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} />
    )
}
Run Code Online (Sandbox Code Playgroud)

响应路线

动态路由的另一个很好的用例是创建响应路由,这在路由器文档和推荐的读取中得到了很好的解释.以下是文档中的示例:

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>
)
Run Code Online (Sandbox Code Playgroud)

总结文档,您会注意到Redirect使用动态路由添加到大屏幕尺寸变得多么简单和声明.在这种情况下使用静态路由将非常麻烦,并且需要我们将所有路由放在一个地方.具有动态路由简化了这个问题,因为现在逻辑变得可组合(如组件).

静态路由

有些问题无法通过动态路由轻松解决.静态路由的一个优点是它允许在渲染之前检查和匹配路由.因此,它在服务器端尤其有用.反应路由器团队还在开发一个名为react-router-config的解决方案,引用该解决方案:

随着React Router v4的推出,不再有集中式路由配置.有一些使用案例,了解所有应用程序的潜在路线是有价值的,例如:

  1. 在渲染下一个屏幕之前,在服务器上或生命周期中加载数据
  2. 按名称链接到路线
  3. 静态分析

希望这提供了动态路由和静态路由以及它们的用例的良好总结:)


Shu*_*tri 5

根据 React-Router 文档:

当我们说动态路由时,我们指的是在您的应用程序呈现时发生的路由,而不是在运行的应用程序之外的配置或约定中。这意味着几乎所有东西都是 React Router 中的一个组件。

它的解释很清楚,您的所有路线都没有在您的应用程序开始时初始化,

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>
Run Code Online (Sandbox Code Playgroud)

通过这个 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>
)
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,只有当 /todos 与 route-path 匹配时,才会挂载 Todo 组件,然后才/todos/:id定义Route 路径。

响应路由

React-router 文档对此有一个很好的用例。

考虑用户导航到/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>
)
Run Code Online (Sandbox Code Playgroud)

将动态路由与 React Router 一起使用,请考虑components,而不是静态路由。

代码拆分

网络的一大特色是我们不必让访问者下载整个应用程序才能使用它。您可以将代码拆分视为增量下载应用程序。This is made possible with Dynamic Routing.

它带来的好处是不需要一次下载所有代码,因此它使初始渲染更快。

是一篇很好的文章,可以帮助您为您的应用程序设置代码拆分

编写可组合的经过身份验证的路由

使用动态路由还可以更轻松地编写 PrivateRoutes(一个进行身份验证的 HOC),它允许对用户进行身份验证并为他们提供对特定路由的访问权限,否则进行重定向。我打的这个电话很笼统

典型的私有路由看起来像

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={props =>
      fakeAuth.isAuthenticated ? (
        <Component {...props} />
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: props.location }
          }}
        />
      )
    }
  />
);
Run Code Online (Sandbox Code Playgroud)

并且可以用作

<PrivateRoute path="/protected" component={Protected} />
Run Code Online (Sandbox Code Playgroud)