React Router Switch 和确切路径

React Router Switch and exact path

我已阅读有关 react-router Switch

的文档

我理解Switch和Route的定义

但还是有些地方没看懂

如果我只想选择一个路由来渲染,我们可以像这样使用 Switch

<Switch>
  <Route exact path="/" component={Home} />
  <Route path="/a" component={A} />
  <Route path="/b" component={B} />
</Switch>

我无法理解的一点是,我可以在没有开关的情况下获得相同的效果

 <Route exact path="/" component={Home} />
 <Route path="/a" component={A} />
 <Route path="/b" component={B} />

那我们为什么要用Switch呢?什么时候需要用到Switch?


我发现了一个需要使用Switch的情况

如果我想在没有路径匹配时渲染特定组件

我们需要像这样在 Switch 中包装 Route

<Switch>
  <Route exact path="/" component={Home} />
  <Route path="/a" component={A} />
  <Route path="/b" component={B} />
  <Route component={SpecificComponent} />
</Switch>

我说得对吗?

虽然在您的情况下您可以使用 exact 获得相同的效果,但情况可能并非总是如此。但是,如果您的其中一个路线包含嵌套路线,如果您在顶层有确切的路线,则无法使用嵌套路线。

Switch 在上述情况下达到了目的,因为它只呈现第一个匹配项

例如,

假设 Home 路线包含嵌套路线,例如

const Home = (props) => (
     <div>
          <Route path="/dashboard" component={Dashboard}/>
          <Route path="/layout" component={Layout}/>
     </div>
)

所以现在如果你写

<Route exact path="/" component={Home} />

当您访问 /dashboard 时。 Dashboard 组件无法呈现,因为没有路由与顶层的 /dashboard 匹配。

为了使示例 运行 正确,您可以使用 Switch 并重新排序路由,以便作为其他路径前缀的路径在末尾

<Switch>
  <Route path="/a" component={A} />
  <Route path="/b" component={B} />
  <Route path="/" component={Home} />
</Switch>

基本上,"exact" 关键字都有相同的用途。 (注意:使用检查当前 URL 是否以此路径开头的匹配算法。)但是当我们使用 时,路由声明或特异性的顺序很重要。需要在顶部添加更具体的 Route。你的情况

<Switch>
<Route path="/a" component={A} />
<Route path="/b" component={B} />
<Route exact path="/" component={Home} />
</Switch>

在"exact"的情况下,当你传递"exact"时,只有路径完全匹配才会匹配这条路由。在您的情况下,主路径设置为准确。

<Route exact path="/" component={Home} />
<Route path="/a" component={A} />
<Route path="/b" component={B} />

让我列出RouteexactSwitch的不同特征:

  • Route 进行部分匹配。 Route 的路径包含匹配(匹配很多)。

  • exact 删除部分匹配。它可能匹配多个路由,以防我们在路由中使用通配符。

  • Switch 只渲染第一个匹配的路由。 Switch 路径完全匹配(只匹配一个)。

为了详细解释,我想说明路由匹配在有和没有 exact 的情况下是如何工作的。假设我们有以下代码并且我们没有使用 exact.

因此,如果我们访问 /pagetwo URL,Route 将进行部分匹配并呈现两条路线。让我们看看它是如何发生的。在下图中,我们正在查看地址栏和我们导航到的路径(提取的路径)以及正在匹配的路由。因此,Route 将在 extractedPath.contains(path-in-our-Route-declaration) 评估为真时呈现路线。

希望阐明 Route 在幕后是如何工作的。为了避免这种部分匹配,我们使用 exact。使用 exact 解决问题,直到我们遇到一些特殊情况。假设我们有两条路线:

  • /users/create
  • /users/*(路由中的通配符)。

在上述情况下,exact 将匹配两条路线。因此,要解决此类问题,我们可以使用 Switch。它只呈现一条路线,并且首先匹配任何路线。因此,这里定义路线的顺序很重要。

React-router-dom 下面使用的是 5.2.0 版本。以下说明不适用于 react-router-verion 6。有关重大更改,请参阅下面随附的 Academind 视频

你说得对!如果我们想在找不到匹配项时渲染特定组件,我们可以使用 switch,但让我解释一下原因。

让我们考虑一个例子来理解exactSwitch

的作用
function App() {

  return <Router>
   
    <Route path="/">
      <Home />     {/* This displays Home Page */}
    </Route>

    <Route path="/about">
      <About />    {/* This displays About Page */}
    </Route>

  </Router>

}

路径 /about 与主页 (/) 和关于页面 (/about) 匹配,因为 /about 等于 / home + about。 换句话说,/about/about(家和周围),所以它呈现两者。

为了避免渲染两个组件,我们在 第一个 出现的组件(在本例中为 /)上使用 exact,以便匹配该公共组件组件就停在那里(home / 是本例中的公共组件,因为它同时出现在 //about 中)。

意义,

/
/about

这两条路线的共同点是/。要在 about 页面停止 / 的匹配,我们在 / 上放置一个名为 exact prop 的限制,以便它在 / 停止匹配并且不会继续查看其他路线。

在具有 / 的更多路线中,将不会呈现主页,因为我们已经在 /(主页)

上添加了 exact 限制
<Route exact path="/">
  <Home />     {/* displays home. Stops matching / for further routes below because of exact prop */}
</Route>

要添加到此示例,现在让我们添加一个动态路由到 /about

 {/* This displays About Page */}
    <Route path="/about">
      <About />
    </Route>

    {/* This displays About Sub Page */}
    <Route path="/about/:id">
      <AboutSubPage />
    </Route>

此时,/about/about/:id(id 可以是 /about/ 之后的任何内容)将再次呈现到屏幕上,如下所示,因为 [=19= 上没有确切的属性].

让我们现在将 exact 属性添加到 /about 页面,以便 /about/2 只呈现关于子页面而不是关于页面

<Route exact path="/about">
  <About />
</Route>

<Route path="/about/:id">
  <AboutSubPage />
</Route>

现在仅显示 /about/2 的 AboutSubPage,如下所示

到目前为止一切顺利,但现在的主要问题是我们在哪里以及为什么需要 Switch ?

比方说,在我们当前的应用程序中,如果有人导航到一个不存在的页面。例如,/hello 不存在。然后我们得到一个空白屏幕,这不是一个好的用户体验。如果我们显示一条友好的消息说“抱歉,该页面不可用”,那就太好了。但是这里的 URL 匹配器应该是什么?我们可以说 *(意思是任何文本)。

<Route path="*">
  <h1>sorry the page is not available </h1>
</Route>

现在这会导致不需要的行为,其中 * 匹配每条路线(甚至是上面提到的路线)。在上述路由中添加的 exact prop 不会阻止这一点,因为通过添加 *,我们说“匹配每条路由并显示 h1”。

现在为了解决只有none以上匹配才考虑*路由(最后添加)的问题,我们使用Switch.

通过使用 Switch 我们说 react-router,“如果其中一条路线匹配,请停止并且不要继续渲染下面的其他路线”。 这样,当它遇到//about时,它只是停止并且不渲染匹配*.

的最后一条路线

万一它没有找到任何路由,就像在 /hello 中一样,它会继续查找直到它匹配 *,然后将我们的消息呈现到屏幕上。

完整代码

function App() {

  return <Router>

    <Switch> {* stops at first route it finds, so that error message at last is not displayed in each and every route *}

      {/* This displays Home Page */}

      <Route exact path="/">
        <Home />
      </Route>

      {/* This displays About Page */}

      <Route exact path="/about">
        <About />
      </Route>

      {/* This displays About Page */}

      <Route path="/about/:id">
        <AboutSubPage />
      </Route>

      <Route path="*">
        <h1>sorry the page is not available </h1>
      </Route>

    </Switch>

  </Router>

}

更新 我们现在有 react-router version 6。有了这个,我们不再 Switch 和 exact

了解重大更改的资源 - https://www.youtube.com/watch?v=zEQiNFAwDGo&ab_channel=Academind