【问题标题】:React Router Switch and exact path反应路由器开关和确切路径
【发布时间】:2019-01-28 09:03:16
【问题描述】:

我已阅读有关react-router Switch 的文档

我理解 Switch 和 Route 的定义

但还是有些看不懂

如果我只想选择一个 Route 来渲染,我们会像这样使用 Switch

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

我不能理解的一点是没有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>

我说的对吗?

【问题讨论】:

    标签: reactjs react-router react-router-v4


    【解决方案1】:

    虽然在您的情况下,您可以使用 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 组件,因为没有 Route 与顶层的 /dashboard 匹配。

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

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

    【讨论】:

    • 感谢您的回答。但是我还是看不懂你的例子,所以如果我们想让例子正常工作,我们需要将 Route 包裹在 Switch 中?
    • 我发现了一个需要使用switch的情况。我更新了我的问题,对吗?
    • @Anymore,是的,当您想在没有匹配项时呈现默认路由时,这是您将使用 switch 的另一种情况
    • 我的回答指定了需要编写嵌套路由的情况
    • 谢谢!。我想知道如何让你的例子正确运行,你能解释一下吗?
    【解决方案2】:

    基本上,“exact”关键字的用途相同。 (注意:使用检查当前 URL 是否以此路径开头的匹配算法。)但是,当我们使用 Route 声明或Specificity 的顺序时。更具体的 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} />
    

    【讨论】:

      【解决方案3】:

      让我介绍一下RouteexactSwitch的不同特点:

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

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

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

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

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

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

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

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

      【讨论】:

        【解决方案4】:

        下面使用的 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(home 和 about),所以它会同时渲染两者。

        为了避免在第一个出现的组件(本例中为/)上渲染我们使用exact的两个组件,以便该公共组件的匹配在此停止(主页/在这种情况下是通用组件,因为它同时存在于 //about)。

        意义,

        /
        /about
        

        这两条路线的共同点是/。为了在about 页面停止/ 的匹配,我们在/ 上设置了一个称为exact 属性的限制,以便它在/ 停止匹配并且不会继续检查其他路由。

        在具有/ 的其他路由中,将不会渲染主页,因为我们已经在/ (home) 上添加了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/ 之后的任何内容)都将再次呈现到屏幕上,如下所示,因为 /about 上没有确切的属性。

        现在让我们将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>
        

        现在这会导致一个不受欢迎的行为,其中 this * 匹配每条路由(甚至是上面提到的路由)。在上述路由中添加的确切属性不会阻止这一点,因为通过添加 *,我们说的是“匹配每条路由并显示 h1”。

        现在,为了解决只有在以上都不匹配时才应考虑 * 路由(最后添加)的问题,我们使用 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 版本 6。有了这个,我们不再Switch和exact

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

        【讨论】:

          猜你喜欢
          • 2019-08-03
          • 2020-08-22
          • 1970-01-01
          • 2022-01-17
          • 1970-01-01
          • 2017-12-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多