前言
在現代Web開發中,React憑借其高效的組件化開發模式和虛擬DOM技術,已成為構建用戶界面的首選庫之一。然而,僅掌握React的核心概念并不足以應對復雜的單頁應用(SPA)開發需求。路由管理作為連接各個頁面、實現視圖切換的關鍵環節,對于提供流暢的用戶體驗至關重要。無論是導航到不同的頁面,還是根據URL動態展示內容,合理設計與實現路由都是每個React開發者必須面對的課題。
本文旨在為讀者提供一個全面而深入的指南,幫助你從基礎到高級全面掌握React路由的應用。無論你是剛剛接觸React的新手,還是希望進一步提升技能的有經驗開發者,“React 路由:一篇就夠了”都將為你揭開React路由管理的神秘面紗。我們將從最基礎的路由配置開始,逐步深入探討如何利用react-router-dom
庫進行頁面導航、參數傳遞、嵌套路由設置,乃至基于權限控制的私有路由實現等高級話題。此外,我們還將介紹懶加載等優化策略,以提高應用性能。通過閱讀這篇文章,你將能夠自信地在自己的項目中實現高效且靈活的路由系統,讓開發過程更加得心應手。讓我們一起開啟這段探索React路由之旅吧!
安裝 react-router-dom?
yarn add react-router-dom
或者npm install?react-router-dom
路由引入
?在App.tsx里引入
import './App.css'
import AppRoutes from './routes/RouterConfig'const App: React.FC = () => {return (<div className="App"><AppRoutes /></div>)
}export default App
路由配置
下面的是路由的配置, 這里使用的是基于history模式的BrowserRouter,當然也可以使用HashRouter包裹(哈希路由),這里還設置了如果進入沒有配置的路由頁面,則會顯示404頁面。
這里也配置了二級路由,同時也加了路由守衛
import { FC } from 'react'
import { BrowserRouter, Route, Routes, Outlet } from 'react-router-dom'
import Login from '@/pages/LoginPage'
import Home from '@/pages/Home'
import About from '@/pages/About'
import NotFoundPage from '@/pages/NotFoundPage'
import PrivateRoute from './PrivateRoute'export const routes = [{ path: '/login', element: <Login />, isPrivate: false },{ path: '/', element: <Home />, isPrivate: true, children: [{ path: 'about', element: <About />, isPrivate: true }] },{ path: '*', element: <NotFoundPage />, isPrivate: false },
]const AppRoutes: FC = () => {// 遞歸渲染路由const renderRoutes = (routes: any) => {return routes.map((route: any) => {let element = route.isPrivate ? <PrivateRoute>{route.element}</PrivateRoute> : route.elementif (route.children) {element = (<>{element}<Outlet /></>)}return (<Route key={route.path} path={route.path} element={element}>{route.children && renderRoutes(route.children)}</Route>)})}return (<BrowserRouter><Routes>{renderRoutes(routes)}</Routes></BrowserRouter>)
}export default AppRoutes
路由守衛?
React的路由守衛(Route Guards)是一種用于控制頁面訪問的機制。它允許你在用戶嘗試訪問某個頁面之前,執行一些邏輯,如驗證用戶身份、檢查頁面權限等。
import { Navigate } from 'react-router-dom'
import { useSelector } from 'react-redux'
import { RootState } from '@/store/index'interface PrivateRouteProps {children: JSX.Element
}// 定義一個私有路由組件
const PrivateRoute: React.FC<PrivateRouteProps> = ({ children }) => {// 從Redux中獲取用戶是否登錄的狀態const isLoggedIn = useSelector((state: RootState) => state.authReducer.isLoggedIn)// 如果用戶已登錄,則渲染子組件,否則重定向到登錄頁面return isLoggedIn ? children : <Navigate to="/login" />
}export default PrivateRoute
路由懶加載
使用懶加載lazy和當網絡異常時的回調組件方式Suspense?
下面是完整的路由配置代碼
import { FC, lazy, Suspense } from 'react'
import { BrowserRouter, Route, Routes, Outlet } from 'react-router-dom'
import PrivateRoute from './PrivateRoute'// 使用 lazy 函數進行懶加載
const Login = lazy(() => import('@/pages/LoginPage'))
const Home = lazy(() => import('@/pages/Home'))
const About = lazy(() => import('@/pages/About'))
const NotFoundPage = lazy(() => import('@/pages/NotFoundPage'))export const routes = [{ path: '/login', element: <Login />, isPrivate: false },{ path: '/', element: <Home />, isPrivate: true, children: [{ path: 'about', element: <About />, isPrivate: true }] },{ path: '*', element: <NotFoundPage />, isPrivate: false },
]const AppRoutes: FC = () => {const renderRoutes = (routes: any) => {return routes.map((route: any) => {let element = route.isPrivate ? <PrivateRoute>{route.element}</PrivateRoute> : route.elementif (route.children) {element = (<>{element}<Outlet /></>)}return (<Route key={route.path} path={route.path} element={<Suspense fallback={<div>加載中……</div>}>{element}</Suspense>}>{route.children && renderRoutes(route.children)}</Route>)})}return (<BrowserRouter><Suspense fallback={<div>Loading...</div>}><Routes>{renderRoutes(routes)}</Routes></Suspense></BrowserRouter>)
}export default AppRoutes
react-router-dom?基本原理
在React應用中,路由跳轉的原理主要依賴于react-router-dom
庫所提供的機制。該庫基于HTML5 History API(包括pushState
、replaceState
等方法)和哈希(hash)模式來管理URL的變化,并通過監聽URL變化來動態加載不同的組件,從而實現頁面的無刷新切換。以下是React路由跳轉的基本原理及其工作流程:
基本原理
-
History API:
react-router-dom
使用了HTML5的History API來操作瀏覽器的歷史記錄棧。這意味著它可以添加或修改歷史記錄條目,使得用戶可以通過前進或后退按鈕導航,而不會觸發整個頁面的重新加載。具體來說,當進行路由跳轉時,它會調用history.push()
或history.replace()
等方法來改變當前的URL路徑。 -
監聽URL變化: 當用戶執行某些動作(如點擊鏈接或瀏覽器的前進/后退按鈕)導致URL發生變化時,
react-router-dom
會監聽到這些變化。這通常通過window
對象上的popstate
事件來實現。一旦檢測到URL變化,它就會根據新的URL路徑來決定應該渲染哪個組件。 -
匹配路由與渲染組件: 根據配置好的路由表,
react-router-dom
會嘗試將當前的URL路徑與定義的路由進行匹配。如果找到匹配項,則會渲染相應的React組件;如果沒有匹配項,則可能會顯示404頁面或其他默認內容
工作流程
-
初始化: 在應用啟動時,
react-router-dom
會首先讀取配置好的路由表,并根據初始URL渲染對應的組件。 -
導航跳轉: 當需要從一個頁面跳轉到另一個頁面時,可以使用
<Link>
組件或者編程方式(如useNavigate
鉤子)來發起跳轉。這會導致URL發生變化,但不會重新加載整個頁面。 -
響應URL變化: URL更新后,
react-router-dom
會監聽到這一變化,并查找與新URL相匹配的路由規則。如果找到了匹配項,就渲染對應的組件;否則,可能展示一個錯誤頁面。 -
狀態管理: 除了基本的路由跳轉外,
react-router-dom
還允許你在跳轉過程中傳遞狀態信息,比如通過查詢參數或者路由狀態等。