ReactJS入門 - 路由 react-router-dom - 筆記長也NotesHazuya

ReactJS入門 - 路由 react-router-dom

2021-07-30 12:53:00   ReactJS

路由

如果從後端過來的朋友們肯定對於路由不陌生,路由會依照不同的路徑來回傳不同的資料或是渲染不同的靜態頁面,簡單來說可以視為網址路徑。

多頁式的渲染方式

一般常見的多頁面網站會由伺服器端回傳完整的 html 網頁檔案,也就是說每一個路由被訪問之後都必須重新產生網頁。

SPA

SPA 與上面的方式不同,無論訪問什麼路由都只會回傳一個 html 檔案,而畫面渲染就會交給 react 或是 JavaScript 處理,此路由稱為前端路由。

前端路由的優點

前端路由由於都交給客戶端渲染,所以對於 server 的效能負載比較低,缺點是在 SEO 部分可能偏弱,不過目前也有針對這方面提出了 SSR 的部分,可以優化 SEO,不過就不在我們的討論範圍之內。關於單頁面與多頁面網站的比較可以參考之前的這篇文章:https://www.notes-hz.com/post/204

安裝 react-router-dom

預設 react 沒有包含這個套件,在專案根目錄下執行指令

npm i react-router-dom

準備兩個元件

我們先準備好兩個元件,分別為 A 與 B ,稍後我們就可以直接拿來使用。

A.js

import React from 'react';
const A = (props)=>{
    return(
        <div style={{ background: "#FFFFFF", width: "100%", height: "100%" }}>
            <h1 style={{color: "#000000"}}>這是頁面A</h1>
        </div>
    )
}
export default A;

B.js

import React from 'react';
const B = (props)=>{
    return(
        <div style={{ background: "#FD3E49", width: "100%", height: "100%" }}>
            <h1 style={{color: "#000000"}}>這是頁面B,快來使用 OnlyMyCast 創立屬於自己的私人頻道!</h1>
        </div>
    )
}
export default B;

HashRouter v.s BrowserRouter

HashRouter

HashRouter 會在路徑加上 「#」符號,在切換不同路由的時候也不會送出 request 請求,會全部交給 JavaScript 主導。

HashRouter 的路徑會長得像這樣:

http://127.0.0.1/#/RouterName

BrowserRouter

BrowserRouter 不會有「#」的符號,但是每次切換不同路由就會發出 request,所以必須後端搭配設定好每次請求只回傳 index.html 頁面。

由於 BrowserRouter 需要後端的搭配,本篇不會提及有關後端的內容,所以此處只介紹 HashRouter ,關於 BrowserRouter 有機會會在後面的文章介紹如何設定。

引入並設定 HashRouter

import { HashRouter } from "react-router-dom";

首先為了能使 react 識別所有 router,所以要在外層先套上 HashRouter 的元件,在 App.js 加上

const App = (props) => {
  return (  
    <HashRouter>

    </HashRouter>
  );
};

準備 Route

再來要設定自己的 route,所有的 route 都會用 <Route> 這個元件來設定,先引入

import {HashRouter,Route} from "react-router-dom";

<Route>元件的基本用法是這樣

<Route path="Route路徑" component={ 用來當頁面的元件「名稱」 } />

引入元件

先將剛剛我們已經設計好的 A 與 B 引入到 App.js

import A from './A';
import B from './B';

加入 <Switch> 元件

其實不加入這個元件, route 切換依然會正常運作,不過這個元件可以只渲染第一個符合條件的 route,什麼意思呢?例如有以下這樣的範例:

      <Route path="/B" component={B}/>
      <Route path="/:type" component={A}/>

:type 是帶有參數的路由,如果今天訪問了 「/B」 這個路由,如果不使用 switch 元件就會造成兩個路由都符合條件,兩者都會被渲染到畫面上,顯然這可能不是我們想要的,因此我們加上 Switch 這個件

import {HashRouter,Route,Switch} from "react-router-dom";
        <HashRouter>
            <Switch>
            </Switch>
        </HashRouter>

再試著以上面的基本用法來分別建立兩個路由:「/」與「/B」,並包在 <Switch> 裡面

      <Route path="/" component={A}/>
      <Route path="/B" component={B}/>

執行之後在瀏覽器去更改不同路徑,應該會出現不同的元件,但是訪問到 「/B」 的時候仍然只顯示元件 A。顯然這不是我們要的,由於 「/B」 已經符合第一個 「/」 的條件,所以只有「/」 被渲染。

exact

我們將「/」路由加上  exact ,意思是必須完全符合路徑才渲染畫面,當只有訪問「/」條件才會成立。

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

加上之後就可以正常訪問不同路由了

URL 參數

必要參數

如果 URL 必須依定要有參數才能進行,在路由名稱這樣設定:

<Route path="/:id" component={B}/>

如果 id 這個參數是空的,路由就不會被訪問

選擇性參數

如果你的路由參數是選擇性的(例如頁數),可以加上「?」:

<Route path="/:page?" component={B}/>

讀取參數

參數會被帶入元件的 props 當中,可以直接使用下列方法抓到 id 的值:

props.match.params.id

如果你的參數叫做 page 的話會是這樣

props.match.params.page

如果你的參數是可選的,那有可能會遇到未定義的數值,要記得處理

props.match / location / history

所有的路由狀態都會被包在這三個物件當中,其中 match 與參數有關係,location 與目前路徑有關,history 則是與路由操作有關係,礙於篇幅關係本篇就不介紹了。

react router v.s react router dom

react router dom 就是基於 react router 再加上一些 dom 的方式來操作路由,所以安裝了 react router dom 就不用再安裝 react router了,已經包含在裡面

 

切換路由 <Link> 元件

<Link> 與 <a>

過去在切換網頁的時候都用 html 內建的 <a> 標籤來做,雖然也可以用來切換 react 的 router ,但是不方便的地方,例如如果使用 HashRouter 要自己在路徑上加上「#」 符號,而且如果一旦應用程式放置的位置變動的話,就必須手動重新設定路徑。

而如果使用 BrowserRouter ,會導致網頁每次都被重新載入,使用效果很不好。

<Link> 用法

先引入

import {Link} from 'react-router-dom';

基本語法會是這樣

<Link to="路徑"> 顯示文字 </Link>

我們來加到上面的範例當中,分別把 A 與 B 改成以下這樣:

A.js

import React from 'react';
import {Link} from 'react-router-dom';
const A = (props)=>{
    return(
        <div style={{ background: "#FFFFFF", width: "100%", height: "100%" }}>
            <Link to="/B">點我連到B</Link>
            <h1 style={{color: "#000000"}}>這是頁面A</h1>
        </div>
    )
}
export default A;

B.js

import React from 'react';
import {Link} from 'react-router-dom';
const B = (props)=>{
    return(
        <div style={{ background: "#FD3E49", width: "100%", height: "1000px", alignItems: "center", justifyItems:"center" }}>
            <Link to="/">點我連到A</Link>
            <h1 style={{color: "#FFFFFF",}}>這是頁面B,快來使用 OnlyMyCast 創立屬於自己的私人頻道!</h1>
        </div>
    )
}
export default B;

再看一下效果

結論

本篇是基本介紹的最後一篇,再來下一篇將會透過實際的專案製作來統整這幾篇文章所學習到的東西。

 

 

關於作者


長也

資管菸酒生,嘗試成為網頁全端工程師(laravel / React),技能樹成長中,閒暇之餘就寫一些筆記。 喔對了,也愛追一些劇,例如火神跟遺物整理師,推推。最愛的樂團應該是告五人吧(?)