react-router 是一個(gè)流行的用于 React 應(yīng)用程序路由的庫。它使我們能夠輕松定義應(yīng)用程序的路由,并將它們映射到特定的組件,這樣可以很容易地創(chuàng)建復(fù)雜的單頁面應(yīng)用,并管理應(yīng)用程序的不同視圖。
react-router 是基于 React 構(gòu)建的,因此與其他 React 庫和工具集成得很好。它在許多 React 應(yīng)用程序中廣泛使用,并被認(rèn)為是 React 中最佳實(shí)踐的路由。
一、react-router-dom安裝和簡介
1. react-router-dom安裝
使用 npm 或?yarn 安裝 react-router-dom。
npm install --save react-router-dom
yarn add react-router-dom
2. react-router-dom 簡介
react-router-dom 是 react-router 的一種實(shí)現(xiàn)方案,主要應(yīng)用于網(wǎng)頁端應(yīng)用,它提供了一些常用的組件進(jìn)行路由管理。
(1) Router 類組件
- BrowserRouter:history 模式下的路由。
- HashRouter:hash 模式下的路由。
(2) Route?組件
Route 是一個(gè)路由配置組件。
(3) Link 組件
Link 類似于 a 標(biāo)簽,可以用于路由跳轉(zhuǎn)。
(4)?useNavigate Hook
useNavigate 是一個(gè)鉤子函數(shù),可以用于路由跳轉(zhuǎn)。
二、react-router-dom 基本使用
1. 引入 react-router-dom
import {BrowserRouter as Router, Routes, Route} from 'react-router-dom';
這里的 BrowserRouter as Router 相當(dāng)于給 BrowserRouter 起了一個(gè)別名叫 Router。Routes 組件用于包裹 Route 組件,Route 組件的父組件必須是 Routes。
2. 簡單使用
使用 BrowserRouter 組件包裹 Routes 組件,再用 Routes 組件包裹 Route 組件,在 Route 組件中定義路由信息,就實(shí)現(xiàn)了一個(gè)簡單的 react-router 場(chǎng)景。
Route 組件有 path 和 element 兩個(gè)屬性,path 屬性代表路由路徑,element 屬性代表要渲染的組件。
index.js
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter as Router} from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Router>
<App />
</Router>
);
app.js
import './App.css';
import { Routes, Route} from "react-router-dom";
import Home from "./views/Home";
import About from "./views/About";
import Error from "./views/Error";
function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={<Home/>}/>
<Route path="/about" element={<About/>}/>
<Route path="*" element={<Error/>}/>
</Routes>
</div>
);
}
export default App;
在上面的案例中,我們定義了一個(gè)根路由,指向 Home 頁面。還定義一個(gè)指定路徑路由 /about,指向 About 頁面,表示當(dāng)我們?cè)跒g覽器地址欄中的頁面地址后加上 /about 時(shí),會(huì)跳轉(zhuǎn)到 About 頁面。
又定義了一個(gè)通用路由,指向 Error 頁面,path="*" 表示如果瀏覽器地址欄中的頁面地址不是以上定義的2種路由(即其他路由地址)時(shí),就會(huì)跳轉(zhuǎn)到 Error 頁面。
注意:BrowserRouter 組件最好放在最頂層所有組件之外,這樣能確保內(nèi)部組件使用 Link 做路由跳轉(zhuǎn)時(shí)不出錯(cuò)。
3. 路由跳轉(zhuǎn)
跳轉(zhuǎn)路由時(shí),如果路由路徑是 / 開頭的是絕對(duì)路由,否則是相對(duì)路由,即相對(duì)于當(dāng)前 URL進(jìn)行改變。
(1) Link 組件
Link 組件只能在 Router 組件的內(nèi)部使用,to 屬性代表要跳轉(zhuǎn)的路由地址。
import { Link } from "react-router-dom";
<Link to="/about">To About</Link>
(2) NavLink 組件
NavLink 組件和 Link 組件的功能是一致的,區(qū)別在于 NavLink 組件可以判斷其 to 屬性是否是當(dāng)前匹配到的路由。
NavLink組件的 style 屬性或 className 屬性可以接收一個(gè)函數(shù),函數(shù)接收一個(gè)含有 isActive 字段的對(duì)象為參數(shù),可根據(jù)該參數(shù)調(diào)整樣式。
import { Link } from "react-router-dom";
<NavLink to="/about" style={({ isActive }) => ( {color: isActive ? "red" : "black"} )}>To About</NavLink>
(3)?useNavigate Hook
使用 useNavigate 鉤子函數(shù),可以在 js 代碼中實(shí)現(xiàn)路由跳轉(zhuǎn)。
useNavigate 必須在 Route 的上下文中使用,即必須包裹在 Router 標(biāo)簽內(nèi)。
import { useNavigate } from "react-router-dom";
<button onClick={() => navigate("/about")}>To About</button>
4. 路由參數(shù)
(1) 路徑參數(shù)(動(dòng)態(tài)路由匹配)
在 Routes?組件內(nèi)定義路由。對(duì)于動(dòng)態(tài)路由,使用冒號(hào)(:)來指定動(dòng)態(tài)部分。例如,要定義一個(gè)動(dòng)態(tài)用戶路由,可以:
App.js
<Routes>
<Route path="/user/:userId" element={<User />} />
</Routes>
這里的 :userId 是動(dòng)態(tài)部分,可以匹配任何放在 /user/ 后面的路徑,比如 /user/123。
在路由的目標(biāo)組件中,可以使用 useParams 鉤子來訪問動(dòng)態(tài)參數(shù)。例如,在 User 組件中,可以這樣獲取 userId:
User.js
mport { useParams } from 'react-router-dom';
function User {
let { userId } = useParams();
console.log(userId); // 123
// 使用 userId 作為你的邏輯的一部分
}
export default User;
上述案例中,訪問 /user/123 能正確獲取到 userId 為123。
(2) 查詢參數(shù)
查詢參數(shù)不需要在路由中定義,可以使用 useSearchParams 鉤子函數(shù)來處理路徑中的查詢參數(shù)。
查詢參數(shù)位于?URL 中,用于提供額外信息以便服務(wù)器能夠更具體地處理請(qǐng)求。它們通常出現(xiàn)在網(wǎng)頁地址(URL)的末尾,并且遵循一定的格式。
在 URL 中,查詢參數(shù)是通過問號(hào)(?)與網(wǎng)址的其它部分分隔開的,并且可以包含一個(gè)或多個(gè)鍵值對(duì)。每個(gè)鍵值對(duì)都由一個(gè)鍵(key)和一個(gè)值(value)組成,用等號(hào)(=)連接。如果有多個(gè)查詢參數(shù),它們之間通常用符號(hào)與(&)分隔。
例如,在 URL?https://example.com/page?param1=value1¶m2=value2?中, param1=value1 和 param2=value2 是查詢參數(shù),它們提供了額外的信息給服務(wù)器。
useSearchParams Hook 返回當(dāng)前組件獲取到的查詢參數(shù)對(duì)象及修改這個(gè)對(duì)象的方法,使用方法和 useState Hook 類似。
在使用?setSearchParams 方法時(shí),必須傳入所有查詢參數(shù),否則會(huì)覆蓋已有查詢參數(shù)。
import { useSearchParams } from 'react-router-dom';
function User() {
// 使用 useSearchParams 鉤子
const [searchParams, setSearchParams] = useSearchParams();
// 獲取查詢參數(shù)
const userId = searchParams.get('userId');
// 設(shè)置查詢參數(shù)
const setUserId = (newUserId) => {
setSearchParams({ userId: newUserId });
};
// 渲染組件
return (
<div>
<p>當(dāng)前的 userId 是:{userId}</p>
<button onClick={() => setUserId('123')}>設(shè)置 userId 為 123</button>
</div>
);
}
export default User;
上述案例中,訪問 /user?userId=123456 時(shí),效果如下:
點(diǎn)擊按鈕后,userId 變?yōu)?123,符合預(yù)期。
(3) 狀態(tài)參數(shù)
react-router 對(duì) window.location 進(jìn)行了包裝,狀態(tài)參數(shù)就位于包裝后的 location 對(duì)象的 state 屬性中。下面為包裝后的 location 對(duì)象的屬性:
pathname | 主機(jī)名之后的 URL 地址 |
search | 查詢參數(shù) |
hash | 哈希值,用于確定頁面滾動(dòng)的具體位置 |
state | 對(duì)于 window.history.state 的包裝 |
key | 每個(gè) location 對(duì)象擁有一個(gè)唯一的 key |
state 不顯示在頁面上,不會(huì)引起頁面刷新,可用于記錄用戶的跳轉(zhuǎn)詳情或在跳轉(zhuǎn)時(shí)攜帶信息,可以用在 Link 組件或 navigate 方法中使用狀態(tài)參數(shù)。
{/* Link 中使用狀態(tài)參數(shù) */}
<Link to="/about" state={{ id: 123 }} >To About</Link>
{/* useNavigate 中使用狀態(tài)參數(shù) */}
<button onClick={() => navigate("/about", { state: { id: 456 } })}>To About</button>
在目標(biāo)組件中,使用 useLocation 來獲取封裝后的 loaction 對(duì)象,進(jìn)而獲取狀態(tài)參數(shù)。
const location = useLocation();
console.log(location.state);
5. 路由重定向
當(dāng)在某個(gè)路徑 /a ,要重定向到路徑 /b 時(shí),可以通過 Navigate 組件進(jìn)行重定向到其他路徑。
import { Navigate } from “react-router-dom”;
function A() {
return <Navigate to=”/b" />;
}
export default A;
三、react-router-dom 進(jìn)階使用
1. 嵌套路由
嵌套路由是前端開發(fā)中用于組織和管理路由的一種技術(shù),特別適用于構(gòu)建具有層次結(jié)構(gòu)的頁面和應(yīng)用程序。
在 Route 組件內(nèi)定義 Route 組件實(shí)現(xiàn)嵌套路由,在父組件中使用 Outlet 組件作為子組件的占位符(顯示匹配到的子組件)。
在嵌套路由中,如果 URL 僅匹配了父級(jí) URL,則 Outlet 組件中會(huì)顯示帶有 index 屬性的子路由,這個(gè)子路由稱為默認(rèn)路由。
例3-1:根據(jù)用戶 id 顯示用戶詳細(xì)信息
App.js
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import Home from './views/Home';
import Users from './views/Users';
import UserList from "./views/UserList";
import UserDetail from "./views/UserDetail";
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link> |
<Link to="/users">User</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="users" element={<Users />}>
<Route index element={<UserList />} />
<Route path=":userId" element={<UserDetail />} />
</Route>
</Routes>
</Router>
);
}
export default App;
Users.js
import { Link, Outlet } from "react-router-dom";
function Users() {
return (
<div>
<h2>Users</h2>
<nav>
<Link to="list">User List</Link>
</nav>
<Outlet />
</div>
);
}
export default Users;
UserList.js
import { Link } from "react-router-dom";
function UserList() {
const users = [
{id: "1", name: 'John'},
{id: "2", name: 'Jane'},
{id: "3", name: 'Mary'},
];
return (
<div>
<h2>User List</h2>
<ul>
{users.map((user) => (
<li key={user.id}>
<Link to={`/users/${user.id}`}>{user.name}</Link>
</li>
))}
</ul>
</div>
);
}
export default UserList;
UserDetail.js
import { useParams } from 'react-router-dom';
function UserDetail() {
const { userId } = useParams();
const users = [
{id: "1", name: 'John'},
{id: "2", name: 'Jane'},
{id: "3", name: 'Mary'},
];
return (
<div>
<h3>User Detail</h3>
<h3>id:{userId}</h3>
<h3>name:{users.find((user) => user.id === userId).name}</h3>
</div>
)
}
export default UserDetail;
上述案例中,在根組件 App 中定義了一組嵌套路由,一級(jí)路由為 / 和 users。又在 users 中嵌套了默認(rèn)路由和動(dòng)態(tài)路由 :userid。
在這個(gè)嵌套路由中,Users 組件為父組件,UserList 和 UserDetail 組件為子組件。在 Users 組件中使用了 Outlet 組件,作為匹配到的子組件的占位符。可以使用在路由的任何層級(jí)。當(dāng)訪問 /users?時(shí),這里觸發(fā)默認(rèn)路由顯示?UserList 組件。當(dāng)訪問 /users/2?時(shí),會(huì)顯示 UserDetail 組件。
訪問 /users:
訪問 /users/2:
2. 多組路由
多組路由指的是在單個(gè)應(yīng)用中設(shè)置多個(gè)獨(dú)立的路由組,可以在不同部分的應(yīng)用中實(shí)現(xiàn)獨(dú)立的路由邏輯,增加了路由結(jié)構(gòu)的靈活性和模塊化。
在 react-router-dom 中,可以通過在不同的組件中定義多個(gè) Routes?組件來實(shí)現(xiàn)多組路由。
例3-2 管理系統(tǒng)案例
App.js
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import MainSite from './views/MainSite';
import AdminPanel from './views/AdminPanel';
function App() {
return (
<Router>
<Routes>
<Route path="*" element={<MainSite />} />
<Route path="admin/*" element={<AdminPanel />} />
</Routes>
</Router>
);
}
export default App;
MainSite.js
import { Routes, Route, Link } from 'react-router-dom';
import Home from './Home';
import About from './About';
function MainSite() {
return (
<div>
<nav>
<Link to="/">Home</Link> |
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</div>
);
}
export default MainSite;
AdminPanel.js
import { Routes, Route, Link } from 'react-router-dom';
import Dashboard from './Dashboard';
import Users from './Users';
function AdminPanel() {
return (
<div>
<nav>
<Link to="/admin/dashboard">Dashboard</Link> |
<Link to="/admin/users">Users</Link>
</nav>
<Routes>
<Route path="dashboard" element={<Dashboard />} />
<Route path="users" element={<Users />} />
</Routes>
</div>
);
}
export default AdminPanel;
上述案例構(gòu)建了一個(gè)具有兩個(gè)獨(dú)立路由組的應(yīng)用,這兩個(gè)路由組分別是主站(MainSite 組件)和管理面板(AdminPanel 組件)。MainSite 組件包含了應(yīng)用的主要頁面,如首頁(Home)和關(guān)于頁面(About);AdminPanel 組件是應(yīng)用的管理面板,包含了儀表盤(Dashboard)和用戶管理(Users)?界面。
App.js 中定義了應(yīng)用的頂級(jí)路由結(jié)構(gòu),使用 Routes?來定義兩個(gè)主要路由路徑:*?和 /admin/*。每個(gè)路徑指向?qū)?yīng)的 MainSite 和 AdminPanel 組件。* 路徑指向 MainSite 組件,該組件處理與主站相關(guān)的子路由。/admin/* 路徑指向 AdminPanel 組件,該組件處理與管理面板相關(guān)的子路由。
當(dāng)訪問 / 時(shí),展示?MainSite 組件和 Home 組件;訪問 /about,展示?MainSite 組件和 About 組件;訪問 /admin,展示?AdminPanel 組件;訪問 /admin/dashboard,展示 AdminPanel 組件和?Dashboard 組件。
3. 布局路由
布局路由是一種組織和管理路由的方式,它允許開發(fā)者將路由與其對(duì)應(yīng)的布局分開管理。這在復(fù)雜的應(yīng)用中特別有用,因?yàn)樗梢詭椭3执a的清晰和模塊化。
布局路由是指一種模式,其中一組路由共享相同的布局組件。這意味著這些路由的所有頁面都將有相同的外觀和感覺,例如共享的頭部和底部導(dǎo)航欄。布局組件負(fù)責(zé)渲染這些共享元素,而特定的子路由則負(fù)責(zé)渲染頁面的主要內(nèi)容。
例3-3 升級(jí)版管理系統(tǒng)案例
App.js
同案例3-2。
MainSite.js
import React from 'react';
import {Routes, Route, Link} from 'react-router-dom';
import Home from './Home';
import About from './About';
import Header from './Header';
import Footer from './Footer';
import Error from "./Error";
function MainSite() {
return (
<div>
<Header />
<nav>
<Link to="/">Home</Link> |
<Link to="/about">About</Link>
</nav>
<Routes>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
{/* 更多主站的路由可以在這里添加 */}
{/* 捕獲所有未匹配的路由并顯示 Error 組件 */}
<Route path="*" element={<Error />} />
</Routes>
<Footer />
</div>
);
}
export default MainSite;
AdminPanel.js文章來源:http://www.zghlxwxcb.cn/news/detail-784848.html
import React from 'react';
import {Routes, Route, Link} from 'react-router-dom';
import Dashboard from './Dashboard';
import Users from "./Users";
import AdminHeader from './AdminHeader';
import AdminFooter from './AdminFooter';
import Error from "./Error";
function AdminPanel() {
return (
<div>
<AdminHeader />
<nav>
<Link to="/admin">Dashboard</Link> |
<Link to="/admin/users">Users</Link>
</nav>
<Routes>
<Route path="" element={<Dashboard />} />
<Route path="users" element={<Users />} />
{/* 更多管理面板的路由可以在這里添加 */}
{/* 捕獲所有未匹配的路由并顯示 Error 組件 */}
<Route path="*" element={<Error />} />
</Routes>
<AdminFooter />
</div>
);
}
export default AdminPanel;
上述案例中,我們?cè)?MainSite 和 AdminPanel 中加入了 Header 和 Footer 布局組件,同時(shí)添加了一個(gè)用于處理所有未匹配路由的 Error 組件。文章來源地址http://www.zghlxwxcb.cn/news/detail-784848.html
到了這里,關(guān)于React07-路由管理器react-router-dom(v6)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!