雖然在極小的專案下,前面章節所學的知識點是很足夠的,但是我們在真正的專案開發上不可能只用前面的知識點而已,因為頁面會隨著專案規模大小越來越複雜,因此我們需要一個能夠幫助我們管理頁面的工具,而這個工具就是 React Router。
React Router 是什麼呢?在說明 React Router 這個之前想先簡單講一個觀念,也就是所謂的 SPA(Single Page Application,中文又稱單頁式應用程式)。
那麼 SPA 是什麼呢?SPA 是一個 Web 開發實作...
...
.....
.......
好,暫停一下,其實這一段開始有點文謅謅了,所以我就簡單解釋就好,其實就是從頭到尾你都在同一頁面的意思,什麼叫做同一頁面呢?後面會慢慢解釋。
剛剛有提到 SPA 中文是「單頁式應用程式」其實就是你從頭到尾都在 index.html
這個頁面上,因此如果是採用 SPA 模式開發的網站,那麼你在瀏覽器的網址列上可能會看到這種形式
https://www.example.com/#/
而這一串就是透過 JavaScript 模擬後端路由形成的 SPA 網頁,那你可能會想說 index.html
呢?怎麼消失了?通常來講 「/
」默認是 index.html
,因此才可以忽略,但也是有一些網站默認是 default.html
、home.html
,而這一段是可以透過伺服器的設置來決定默認首頁是哪一個,但通常默認會是 index.html
。
那麼在 SPA 還沒有流行之前,早期都是使用 MPA (Multi Page Application,中文又稱多頁式應用程式)的方式開發,所以你會看到瀏覽器網址列像這樣子呈現
https://www.example.com/user/profile
而不會有 /#/
的形式,因為一段 #/
就是由前端模擬後端路由的一種形式,雖然也可以調整成類似 MPA 的路由形式,但這個必須要與後端搭配才可以,因此 SPA 開發上大多還是以 /#/
模擬為主,而這種模式又稱之為 hash mode
。
但這一點並不是我們要了解的知識,如果想更深入了解的話,可以考慮閱讀我先前寫的這一篇 淺談 SPA、CSR、SSR、MPA、SSG 專有名詞
那麼前面對於 SPA 有一個簡單基本概念之後 React Router 就是要幫助我們做這件事情的重要核心,因此接下來你可以打開任何一個專案,例如前面章節我們所建立的 Vite TodoList 專案也可以,並在終端機輸入以下指令安裝 React Router
npm install --save react-router-dom
而這邊我會使用前面所建立的 example-vite-react 當作示範,你也可以趁機會現在下載或者建立一個新專案。
首先第一個步驟先打開 App.jsx 引入 import { HashRouter } from "react-router-dom";
,而這個 HashRouter
本身就是一個元件概念,接著只需要使用它將整個 <App />
包起來即可
import React from 'react'
import { HashRouter } from "react-router-dom";
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<HashRouter>
<App />
</HashRouter>
</React.StrictMode>
)
恭喜你!你已經成功引入了 React Router 囉!接下來我們就可以開始使用它了。
接下來我們要來認識另一個東西,也就是 Route
。
Route
主要是用來定義路徑跟 Components 之間的關係,你也可以把它想像成「綁定」的概念,舉例來講如果你希望使用者訪問的路徑是以下
https://www.example.com/#/todolist
那麼你在使用 Route
的時候就可以這樣寫
<Route path="/todolist" element={ <ToDoList/> }>
而常見的屬性主要會有兩個
path
:定義路徑element
:定義對應的元件到目前為止,這是一個基本的 Route
使用方式。
事不宜遲,就來把原本寫在 App.jsx 的 ToDoList
挪出來放到另一個元件內,例如叫做 ToDoList.jsx,而 App.jsx 則改成以下
const App = () => {
return (
<h1>App</h1>
)
}
export default App;
接下來就是打開 main.jsx 引入 ToDoList.jsx 並搭配 Route
一起使用
import React from 'react'
import { HashRouter, Route } from "react-router-dom";
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import ToDoList from "./TodoList";
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<HashRouter>
<Route path="/" element={ <App /> } />
<Route path="/todolist" element={ <ToDoList /> } />
</HashRouter>
</React.StrictMode>
)
接下來當你輸入 npm run dev
啟動專案,並在瀏覽器上輸入 http://localhost:3000/#/todolist
你會發現畫面一片空白,並且控制台會出現以下錯誤訊息
Uncaught Error: A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.
這邊我是刻意示範一個錯誤的寫法,其實簡單來講 <Route>
只能包在 <Routes>
底下使用,因此正確來講必須這樣寫才對
import React from 'react'
import { HashRouter, Route, Routes } from "react-router-dom";
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import ToDoList from "./TodoList";
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<HashRouter>
<Routes>
<Route path="/" element={ <App /> } />
<Route path="/todolist" element={ <ToDoList /> } />
</Routes>
</HashRouter>
</React.StrictMode>
)
接下來你重新 npm run dev
的時候應該會看到滿空白的,只有很孤單寂寞覺得冷的一段話「App」,這是很正常的,因為首頁就是這樣子。
但...我們該如何進入 todolist
呢?你可以先試著在瀏覽器網址列輸入 http://localhost:3000/#/todolist
,這樣子你就可以看到「ToDoList」出現在畫面上囉。
那麼今天就先到這邊結束,後面我們還會繼續講解 React Router 的其他使用方式,例如 巢狀路由、Link
、NavLink
等等。
範例程式碼:React Router Example
本文將會同步更新到我的部落格