React?Router掌握路由搭建與權(quán)限管控的操作方法(?從入門到精通)
一、前言
react-router 庫在 React 應(yīng)用開發(fā)中扮演著至關(guān)重要的角色,它是實現(xiàn)頁面路由管理的核心工具,能夠讓開發(fā)者根據(jù)不同的 URL 路徑精準(zhǔn)地渲染對應(yīng)的組件,這對于構(gòu)建流暢、交互性強(qiáng)的單頁面應(yīng)用(SPA)來說不可或缺。通過它,用戶在瀏覽應(yīng)用時無需頻繁刷新整個頁面,就能實現(xiàn)頁面內(nèi)容的動態(tài)切換,極大地提升了用戶體驗。
例如,許多知名的 React 應(yīng)用,如一些大型的電商平臺前端、在線辦公軟件等,都借助 react-router 來管理繁多的頁面路由,實現(xiàn)復(fù)雜的功能模塊切換和頁面導(dǎo)航,使得用戶可以方便快捷地在各個功能頁面之間穿梭。
一般來說,React-Router v6 需要 React v16.8 或更高版本。因為 React-Router v6 利用了 React 的 Hooks 等特性,而 React v16.8 是第一個引入 Hooks 的版本。如果使用較低版本的 React,可能會導(dǎo)致 React-Router 無法正常工作或某些功能缺失。
二、安裝
- 使用 npm 安裝(推薦)
- 打開終端,進(jìn)入 React 項目目錄。
- 若沒安裝 React 項目,可用 Create React App 等創(chuàng)建新項目。
- 在項目目錄下,運(yùn)行
npm install react-router-dom命令,安裝成功后,可查看node_modules目錄有無react-router-dom文件夾,或在代碼文件導(dǎo)入相關(guān)模塊(如import { BrowserRouter } from'react-router-dom')驗證,無報錯即安裝正確。
使用 yarn 安裝
- 打開終端,進(jìn)入 React 項目目錄。
- 運(yùn)行
yarn add react-router-dom命令,完成后即可使用。
三、基礎(chǔ)使用
項目 React 版本: 18.3.1;react-router-dom 版本:7.1.1。
設(shè)置路由基礎(chǔ)結(jié)構(gòu)
在 React 應(yīng)用入口文件(通常是 index.js 或 main.js),用 BrowserRouter(基于瀏覽器歷史記錄,URL 更自然)或 HashRouter(特殊部署需求或兼容舊瀏覽器)包裹整個應(yīng)用。如在 main.js 中:
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App.jsx';
createRoot(document.getElementById('root')).render(
<StrictMode>
<Router>
<App />
</Router>
</StrictMode>
);這里將 App 組件包裹在 Router(BrowserRouter 的別名)中,這樣 App 組件及其子組件就可以訪問到路由相關(guān)的功能。
定義路由和組件關(guān)聯(lián)
在 App 組件或其他組件內(nèi),用 Route 組件定義路由規(guī)則。
直接在組件中定義路由
這種方式將路由定義直接放在組件內(nèi)部,對于小型應(yīng)用或者路由規(guī)則比較簡單的情況,具有直觀的優(yōu)點。開發(fā)者可以一目了然地看到某個組件與具體路由路徑的關(guān)聯(lián)情況,并且路由規(guī)則與組件緊密結(jié)合,很適合組件自身內(nèi)部的路由管理,尤其當(dāng)組件是獨(dú)立的功能模塊時,能使模塊功能更加內(nèi)聚。
import React from 'react';
import { Route } from 'react-router-dom';
import Home from './Home';
import About from './About';
const App = () => {
return (
<div>
{/*
Route 組件定義路由,exact 精確匹配,確保路徑完全是'/'才渲染 Home 組件,
訪問'/about'時不會渲染 Home 組件。訪問'/'渲染 Home 組件,訪問'/about'渲染 About 組件。
*/}
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</div>
);
}
export default App然而,當(dāng)應(yīng)用規(guī)模逐漸變大,路由規(guī)則變得復(fù)雜時,這種寫法會暴露出明顯的缺點。比如在一個大型電商應(yīng)用中,若有上百個路由都寫在 App 組件內(nèi),代碼會變得極為臃腫,查找特定路由關(guān)聯(lián)的組件、修改路由參數(shù)等維護(hù)操作將變得異常繁瑣,代碼的可讀性也會大打折扣,不利于后續(xù)的開發(fā)和維護(hù)。
定義單獨(dú)一個路由表
單獨(dú)創(chuàng)建一個路由表可以將所有的路由規(guī)則集中管理,這對于大型應(yīng)用開發(fā)來說尤為重要。在開發(fā)過程中,開發(fā)者能夠在一個文件中清晰地查看所有的路由路徑、對應(yīng)的組件以及可能的路由參數(shù)等關(guān)鍵信息。而且,路由表具備良好的復(fù)用性,比如在不同的布局組件(如具有不同側(cè)邊欄的布局)中,都可以引用這個統(tǒng)一的路由表來實現(xiàn)相同的路由功能,無需重復(fù)配置。同時,當(dāng)需要對路由規(guī)則進(jìn)行修改時,只需在路由表文件中操作即可,無需逐個在使用路由的組件中進(jìn)行修改,極大地提高了開發(fā)效率和代碼的可維護(hù)性。隨著應(yīng)用的不斷發(fā)展,添加新路由也十分方便,并且對于路由的中間件(如權(quán)限驗證,只有登錄用戶才能訪問某些路由)等功能,在路由表中也能更便捷地進(jìn)行配置。
創(chuàng)建 routes.js 文件定義路由表,集中管理路由規(guī)則。
import { lazy } from 'react';
// lazy 用于設(shè)置路由懶加載
const Home = lazy(() => import('@/pages/Home'));
const About = lazy(() => import('@/pages/About'));
const Router = [
{
path: '/',
element: <Home />
},
{
path: '/about',
element: <About />
},
// 設(shè)置 404 頁面
{
path: '*',
element: <NotFound />
}
];
export default Router然后在 App 組件中使用這個路由表:
import router from './router';
import { Suspense } from 'react';
import { useRoutes } from 'react-router-dom';
function App() {
// useRoutes 依傳入路由配置生成相應(yīng)路由元素,代表應(yīng)渲染組件樹結(jié)構(gòu)。
const element = useRoutes(router);
// Suspense 設(shè)頁面跳轉(zhuǎn)加載提示,組件加載時顯示 fallback 指定內(nèi)容。
return <Suspense fallback={'loading...'}>{element}</Suspense>;
}
export default App此方式適用于大型應(yīng)用,復(fù)用性好,修改路由便捷,還方便配置中間件(如權(quán)限驗證)。
創(chuàng)建導(dǎo)航鏈接
使用 Link 組件來創(chuàng)建應(yīng)用內(nèi)部的導(dǎo)航鏈接,它與傳統(tǒng)的 標(biāo)簽不同,當(dāng)用戶點擊 Link 組件時,不會引起整個頁面的刷新,而是通過 JavaScript 更新 URL 并觸發(fā)相應(yīng)的組件渲染,實現(xiàn)單頁面應(yīng)用內(nèi)的無縫導(dǎo)航。
import React from 'react';
import { Link } from 'react-router-dom';
const Navigation = () => {
return (
<nav>
{/*
Link 組件 to 屬性指定導(dǎo)航目標(biāo)路徑,點擊'Home'鏈接導(dǎo)航到根路徑渲染 Home 組件,
點擊'About'鏈接導(dǎo)航到'/about'路徑渲染 About 組件。
*/}
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
);
}
export default Navigation四、核心組件和功能
BrowserRouter 和 HashRouter
- BrowserRouter:基于 HTML5 瀏覽器歷史記錄 API,URL 格式自然,無“#”符號,如電商產(chǎn)品詳情頁 URL 可為“/products/123”,利于 SEO。
- HashRouter:用 URL 哈希部分管理路由,適用于舊瀏覽器或服務(wù)器不支持 HTML5 歷史記錄 API 的情況,部署在簡單靜態(tài)服務(wù)器上表現(xiàn)良好。
Route 組件
Route 組件是核心,定義路由規(guī)則,關(guān)聯(lián) URL 路徑與組件。
import React from 'react';
import { Route, BrowserRouter as Router } from 'react-router-dom';
import Home from './Home';
import About from './About';
const App = () => {
return (
<Router>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Router>
);
}
export default Appexact 屬性精確匹配路徑,避免誤渲染。
Link 組件
與傳統(tǒng) <a> 標(biāo)簽不同,點擊不刷新頁面,更新 URL 觸發(fā)組件渲染。
import React from 'react';
import { Link } from 'react-router-dom';
const Navigation = () => {
return (
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
);
}
export default NavigationSwitch 組件
包裹一組 Route 組件,只渲染第一個匹配成功的 Route,防止多個組件同時渲染。
import React from 'react';
import { Route, Switch, BrowserRouter as Router } from 'react-router-dom';
import Home from './Home';
import About from './About';
import NotFound from './NotFound';
const App = () => {
return (
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route component={NotFound} />
</Switch>
</Router>
);
}
export default App在這個例子中,如果沒有Switch組件,當(dāng)用戶訪問一個不存在的路徑時,NotFound組件和前面可能部分匹配的組件(比如Home組件)都可能會被渲染。有了Switch組件,只有NotFound組件會被渲染,因為前面的路由都沒有匹配成功
五、路由參數(shù)和嵌套路由
路由參數(shù)
React-Router 允許在路由路徑中定義參數(shù)。例如,在一個列表中,內(nèi)容詳情頁的路由可以定義為 /articles/:id,其中 :id 是一個參數(shù),表示詳情的唯一標(biāo)識符。在組件中可以通過 props.match.params 獲取這個參數(shù)。
import React from 'react';
import { Route, BrowserRouter as Router } from 'react-router-dom';
const ArticleDetail = props => {
const articleId = props.match.params.id;
// 根據(jù) articleId 獲取文章詳情并渲染
return (
<div>
<h1>Article Detail {articleId}</h1>
</div>
);
}
const App = () => {
return (
<Router>
<Route path="/articles/:id" component={ArticleDetail} />
</Router>
);
}
export default App用戶訪問 /articles/123 時,articleId 為“123”。
嵌套路由
復(fù)雜應(yīng)用有嵌套路由情況,如電商產(chǎn)品詳情頁有評論區(qū)。
import React from 'react';
import { Route, BrowserRouter as Router, Switch } from 'react-router-dom';
import ProductDetail from './ProductDetail';
import ProductReviews from './ProductReviews';
const App = () => {
return (
<Router>
<Switch>
<Route path="/products/:id" component={ProductDetail}>
<Route path="/products/:id/reviews" component={ProductReviews} />
</Route>
</Switch>
</Router>
);
}
export default App訪問“/products/123/reviews”時,先渲染 ProductDetail 組件,再在其內(nèi)部合適位置渲染 ProductReviews 組件。
嵌套路由層級加深及應(yīng)用場景拓展
以企業(yè)級應(yīng)用為例,展示部門詳情頁、員工列表頁、員工個人詳情頁和員工績效頁等多層嵌套路由場景,通過合理配置實現(xiàn)頁面有序切換。
import React from 'react';
import { Route, BrowserRouter as Router, Switch } from 'react-router-dom';
const DepartmentDetail = props => {
return (
<div>
<h1>Department Detail</h1>
{/* 展示部門相關(guān)信息 */}
<Route path={`${props.match.path}/employees`} component={EmployeeList} />
</div>
);
}
const EmployeeList = props => {
return (
<div>
<h2>Employee List</h </div>
{/* 展示員工列表 */}
<Route path={`${props.match.path}/:employeeId`} component={EmployeeDetail} />
<Route path={`${props.match.path}/:employeeId/performance`} component={EmployeePerformance} />
</div>
);
}
const EmployeeDetail = props => {
const { employeeId } = props.match.params;
return (
<div>
<h3>Employee Detail - ID: {employeeId}</h3>
{/* 展示員工個人詳細(xì)信息 */}
</div>
);
}
const EmployeePerformance = props => {
const { employeeId } = props.match.params;
return (
<div>
<h3>Employee Performance - ID: {employeeId}</h3>
{/* 展示員工績效相關(guān)信息 */}
</div>
);
}
const App = () => {
return (
<Router>
<Switch>
<Route path="/departments/:departmentId" component={DepartmentDetail} />
</Switch>
</Router>
);
}
export default App通過這樣的復(fù)雜示例,可以更好理解嵌套路由在構(gòu)建大型、功能豐富的應(yīng)用中是如何發(fā)揮作用的,以及如何根據(jù)實際業(yè)務(wù)需求去設(shè)計和配置多層嵌套的路由結(jié)構(gòu),更好地應(yīng)對復(fù)雜的頁面關(guān)系和功能模塊劃分
六、編程式導(dǎo)航
除 Link 組件,React-Router 支持編程式導(dǎo)航,通過 history 對象實現(xiàn),可在組件中用 props.history 獲?。ńM件需通過 Route 組件渲染)。
import React from 'react';
import { Route, BrowserRouter as Router, useNavigate } from 'react-router-dom';
const MyComponent = props => {
const Navigate = useNavigate();
const handleClick = () => {
Navigate('/about');
}
return (
<div>
<button onClick={handleClick}>Go to About</button>
</div>
);
}
const App = () => {
return (
<Router>
<Route path="/" component={MyComponent} />
</Router>
);
}
export default App點擊按鈕,調(diào)用 handleClick 函數(shù),導(dǎo)航到“/about”路徑,適用于表單提交成功等內(nèi)部邏輯導(dǎo)航。
七、路由權(quán)限
路由表
import { lazy } from 'react';
import Auth from './AuthRoute';
const Home = lazy(() => import('@/pages/Home'));
const About = lazy(() => import('@/pages/About'));
const List = lazy(() => import('@/pages/List'));
const User = lazy(() => import('@/pages/User'));
const NotFound = lazy(() => import('@/pages/NotFound'));
const Router = [
{
path: '/',
element: <Home />
},
{
path: '/about',
element: <About />
},
{
path: '/app/',
element: (
// 自定義權(quán)限組件
<Auth>
<BasicLayout />
</Auth>
),
errorElement: <NotFound></NotFound>,
children: [
{
path: 'list',
element: <List />
},
{
path: 'list/user',
element: <User />
}
]
},
// 設(shè)置404頁面
{
path: '*',
element: <NotFound />
}
];
export default Router權(quán)限組件
import { useEffect, useRef } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { message } from 'antd';
import useUpdateEffect from '@/components/useUpdateEffect';
export default function Auth({ children }: any) {
const location = useLocation().pathname;
const didMountRef = useRef(false);
const Navigate = useNavigate();
const token = localStorage.getItem('token');
useEffect(() => {
if (didMountRef.current) {
if (!token) {
message.error('您未登錄,將跳轉(zhuǎn)');
setTimeout(() => {
Navigate('/login');
}, 1000);
}
} else {
didMountRef.current = true;
}
}, [token]);
return children;
}404 頁面
import React from 'react'; const CommonLine = props => ( // 根據(jù)個人需求改動 <div>未找到該頁面</div> ); export default CommonLine
到此這篇關(guān)于React Router 一站式攻略:從入門到精通,掌握路由搭建與權(quán)限管控的文章就介紹到這了,更多相關(guān)React Router 路由搭建與權(quán)限管控內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React Native中ScrollView組件輪播圖與ListView渲染列表組件用法實例分析
這篇文章主要介紹了React Native中ScrollView組件輪播圖與ListView渲染列表組件用法,結(jié)合實例形式詳細(xì)分析了ScrollView組件輪播圖與ListView渲染列表組件具體功能、使用方法與操作注意事項,需要的朋友可以參考下2020-01-01
React Native中WebView與html雙向通信遇到的坑
這篇文章主要介紹了React Native中WebView與html雙向通信的一些問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-01-01
React利用scheduler思想實現(xiàn)任務(wù)的打斷與恢復(fù)
這篇文章主要為大家詳細(xì)介紹了React如何利用scheduler思想實現(xiàn)任務(wù)的打斷與恢復(fù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2024-03-03
詳解create-react-app 自定義 eslint 配置
這篇文章主要介紹了詳解create-react-app 自定義 eslint 配置,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06
React性能優(yōu)化系列之減少props改變的實現(xiàn)方法
這篇文章主要介紹了React性能優(yōu)化系列之減少props改變的實現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01

