[ Day 21 ] 路由管理 - React Router 2/2

https://ithelp.ithome.com.tw/upload/images/20211004/20134153J0Fxp1uOlw.png
在上一篇 Day 20 我们介绍了 React Router 的基本概念以及 React Router Dom 的三大类别元件的其中一个 Routes 的部分。那今天就要接续为大家来介绍剩下的两个类别:Route MatchersNavigation


Route Matchers

包含了 <Route><Switch> 两个 Route Matching 元件,透过两个元件的搭配能够将路径指向对应的元件并判别当中是否有符合对应路径的元件。

而这个类别内也包含两种元件,那这两个元件是代表什麽意思?又分别有什麽功能?

  • <Route> :用来指定元件所要对应的路径
  • <Switch>:通常会使用在 <Route> 的父层并在遍历所有的子元件 <Route> 之後,将其中第一个符合的对应路径的元件渲染出来

下面我们直接看官方文件的范例该怎麽使用?

import React from "react";
import ReactDOM from "react-dom";
import {
  BrowserRouter as Router,
  Switch,
  Route
} from "react-router-dom";

function App() {
  return (
    <div>
      <Switch>
        <Route path="/about">
          <About />
        </Route>
        <Route path="/contact/:id">
          <Contact />
        </Route>
        <Route path="/contact">
          <AllContacts />
        </Route>
        <Route path="/">
          <Home />
        </Route>
      </Switch>
    </div>
  );
}

ReactDOM.render(
  <Router>
    <App />
  </Router>,
  document.getElementById("root")
);

上面的范例中,我们使用了 <Route> 元件并在该元件内部给於一个 path 属性来指定路径的 url ,而在 <Route> 的内层再引入我们要渲染的元件。这样当路径指定到对应的 url 时,画面上就会显示该路径下的那个元件了。

而将 <Switch> 加入到 <Route> 的父层之後, <Swith> 元件会搜寻其所包覆的所有 <Route> 中的 path 是否有符合对应的 url ? 若确认有符合的话,才会将第一个有符合的元件渲染出来。

不过这边关於 <Route><Switch> 分别都有要注意的地方:

关於 <Switch> 的特点

刚刚的说明以及范例中我们都知道了 <Switch> 如果使用在 <Route> 的父层时它会遍历所有 <Route> 元件中的 url ,只要有符合路径的第一个 <Route> 就会渲染出来。但是这边要特别注意,在 Route Matching 元件中对比符合路径的规则是path 最左边开始进行路径对比的

所以大家有发现吗?在上面的范例中,我们将包覆 <Home /> 这个元件的 <Route> 路径指定为 path="/"将它放在所有路由的最下方,原因就是出在这边。
如果我们将 <Home /> 这个元件摆在所有的 <Route> 上方的话,这样 path 的 url 无论怎麽改变都会符合到 <Home /> 的路径: path="/" (因为每个 path 都包含了 / ),这样也会导致即便切换了 url 之後,画面还是只会显示 <Home /> 这个元件的 bug 产生。

那除了将该元件移动到所有 <Route> 最下方之外,还有别的解决办法吗?答案是有的,下面我们就要来看 <Route> 的其他属性怎麽帮助我们解决这个状况?

关於 <Route> 的属性

<Route> 这个 Route Matching 元件中其实具备了三个属性提供你做设定:

  1. path : 设定该元件的路径 url 。
  2. component :设定该路由要渲染出的元件。
  3. exact :加入此属性後,当路径完全等於 path 的 url 时才会确实渲染元件。

了解了 <Route> 这三个属性之後,我们试着将上面的范例用这些属性来改写一下:

import React from "react";
import ReactDOM from "react-dom";
import {
  BrowserRouter as Router,
  Switch,
  Route
} from "react-router-dom";

function App() {
  return (
    <div>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/contact" component={AllContacts} />
        <Route path="/contact/:id" component={Contact} />
      </Switch>
    </div>
  );
}

ReactDOM.render(
  <Router>
    <App />
  </Router>,
  document.getElementById("root")
);

改写之後可以看到,透过 <Route> 这些属性我们可以把路由管理整理得更清楚明了!而且只要修正 <Route> 的属性就可以调整我们所需的东西,让我们在开发的过程也更好做管理。


Navigation

包含了 <Link><NavLink><Redirect> 三个 Route Changers 元件,分别有各自的功能:

<Link>

<Link to="/">Home</Link>
/* 渲染的结果会为:<a href="/">Home</a> */

<Link> 元件会将你在 to 参数上所设定的路径转换成 <a> 标签的连结,让你可以把设定好的路由绑定到你的内容上。

备注:这边关於 <Link> 的详细介绍可以参考 Andy 大大的:【React.js入门 - 28】 我要更多更多的分页 - react-router-dom (下) ,里面有更清楚的说明!

<NavLink>

<NavLink to="/react" activeClassName="hurray">
  React
</NavLink>

<NavLink> 也是采用 <Link> 元件的概念,但是它可以额外设定一个属性 activeClassName :当目前的 url 的路径确实吻合 <NavLink> 里面 to 属性所指定的路径时,这个指定的 className 才会被触发。

所以针对上面的程序码,对於它渲染的结果我们可以这样解读:

/* 当路径的 URL 完全符合 /react 时,渲染以下的内容 */
<a href="/react" className="hurray">React</a>

/* 当路径的 URL 不符合 /react 时,渲染以下的内容 */
<a href="/react">React</a>

<Redirect>

<Redirect to="/login" />

<Redirect> 可以将路由重新连结到指定的路径,大部分是用在画面要重新导向或是所有的 <Route> 都无法正确的渲染对应的元件时才会使用。且通常 <Redirect> 都会加入到路由管理的最下方,如下方范例:

function App() {
  return (
    <div>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/contact" component={AllContacts} />
        <Redirect to="/" />
      </Switch>
    </div>
  );
}

关於 React.js 路由的管理和 React Router Dom 的介绍就到这边告一个段落了。
意外发现 React Router 跟 Vue Router 的功能比较起来好像大同小异(不过也有可能是我还没真的用 React.js 开发过),但是 React Router 的元件和方法的命名真的相对来说更直观更贴切,比较容易记得起来。

明天就要进入 React.js 中的状态管理: Redux 了。听说这是大部分初学者刚接触 React.js 时比较难入手的地方,所以有点紧张 XD
那如果有任何问题一样非常非常欢迎提出和指教喔!
我们下篇见ʘ‿ʘ


<<:  [Day22] Flutter GetX with Dio (一)

>>:  Who Pod Who

[Day 1] 微解封 微服务 那你有听过微框架吗? 又为何我选择 Ktor?

自从微解封之後,现在「微XX」已经成为流行语,原来 Web 後端流行的「微服务」架构已经超前部署好几...

Day5 用Scanner实作一支程序

在Day3时,我们有实做一支计算平行四边形的程序,但当时我们固定了平行四边形的底跟高,现在我们已经学...

【Day23】SwiftUI Essentials - SwiftUI 基础

在这边先声明,这篇是是WWDC大会的部分翻译,我找到的也是别人翻译以及笔记的 文章,只是我觉得很适合...

每个人都该学的30个Python技巧|技巧 8:进阶判断—巢状判断式(字幕、衬乐、练习)

昨天教的是判断式,那它会用到程序区块,那Python要怎麽显示程序区块呢?是要用冒号以及缩排来显示,...

JavaScript入门 Day03_输出文字

那今天终於要来开始打code了!! 就从最基本的 Hello World开始吧 每一款程序语言最基本...