v5
简介
React Router v5 是 React 生态中较早期的路由方案,虽然目前已被 v6 取代,但在许多遗留项目或旧项目中仍被使用。以下是 React Router v5 的基本用法和核心概念,帮助你快速掌握其使用方式。
一、安装与基础结构
React Router v5 需要安装 react-router-dom
包,并通过 BrowserRouter
、Route
、Switch
等组件实现路由功能。
npm install react-router-dom@5.x
1. 基础路由配置
import { BrowserRouter, Route, Switch } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
<Route path="*" component={NotFound} /> {/* 404 页面 */}
</Switch>
</BrowserRouter>
);
}
注意:
<Switch>
是必须的,它会匹配第一个满足条件的<Route>
,避免多个路由同时渲染。
二、导航方式
1. 声明式导航( <Link>
)
使用 <Link>
组件实现页面跳转,类似于 v6 的 <Link>
。
<Link to="/home">首页</Link>
<Link to="/about">关于</Link>
2. 编程式导航( <Redirect>
和 useHistory
钩子)
<Redirect>
:用于手动跳转页面。
import { Redirect } from 'react-router-dom';
function LoginPage() {
if (isLoggedIn) {
return <Redirect to="/home" />;
}
return <div>登录页面</div>;
}
useHistory
钩子:用于动态跳转(React Hooks API)。
import { useHistory } from 'react-router-dom';
function Home() {
const history = useHistory();
const handleClick = () => {
history.push('/about');
};
return <button onClick={handleClick}>跳转到 About</button>;
}
三、动态路由与参数
1. 动态路由参数
通过 :param
定义动态路由参数,使用 match.params
获取参数。
<Route path="/user/:id" component={User} />
获取参数:
import { withRouter } from 'react-router-dom';
function User({ match }) {
const { id } = match.params;
return <div>用户ID: {id}</div>;
}
2. 搜索参数
使用 location.search
获取 URL 中的查询参数:
import { withRouter } from 'react-router-dom';
function SearchPage({ location }) {
const { q } = new URLSearchParams(location.search);
return <div>搜索关键词: {q}</div>;
}
四、嵌套路由
1. 定义嵌套路由
使用 Route
的 children
属性渲染子路由内容,搭配 Switch
实现嵌套。
<Route path="/layout">
<Route path="home" component={Home} />
<Route path="about" component={About} />
</Route>
2. 渲染子路由
使用 Outlet
组件(需要 react-router-dom@5.2.0
或以上版本):
import { Outlet } from 'react-router-dom';
function Layout() {
return (
<div>
<Header />
<Outlet /> {/* 渲染子路由内容 */}
</div>
);
}
五、路由守卫(导航守卫)
React Router v5 通过 component
、render
或 children
实现导航控制,没有现成的 beforeRoute
等钩子。
1. 权限校验(基于 component
)
<Route path="/private" component={PrivateRoute} />
PrivateRoute
组件:
function PrivateRoute({ component: Component, ...rest }) {
const isAuthenticated = checkAuth(); // 自定义校验逻辑
return (
<Route
{...rest}
render={props =>
isAuthenticated ? <Component {...props} /> : <Redirect to="/login" />
}
/>
);
}
2. 路由守卫(基于 component
)
<Route
path="/user/:id"
render={props => {
if (isUserExist) {
return <User {...props} />;
}
return <Redirect to="/404" />;
}}
/>
六、路由模式(Hash/History)
1. Hash 模式
使用 BrowserRouter
的 hashHistory
,默认基于 window.location.hash
实现:
import { HashRouter } from 'react-router-dom';
function App() {
return (
<HashRouter>
<Switch>
<Route path="/home" component={Home} />
<Route path="*" component={NotFound} />
</Switch>
</HashRouter>
);
}
2. History 模式
需要服务器支持 history
模式,如 Nginx 配置:
location / {
try_files $uri $uri/ /index.html;
}
v6
一、核心概念与结构
1. 路由配置
React Router v6 使用 declarative routing(声明式路由) ,通过函数组件和路由配置来定义路由规则。
2. <Routes>
和 <Route>
组件
<Routes>
是嵌套的路由容器,必须包裹在<Routes>
中。<Route>
用于定义路由路径和组件对应的映射关系。
import { Routes, Route } from 'react-router-dom';
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NotFound />} /> {/* 404 页面 */}
</Routes>
);
}
⚠️ 注意:
v6 中
<Route>
的component
属性已被弃用,改为element
,并需要传入一个 JSX 元素。
二、导航方式
1. 声明式导航( <Link>
)
使用 <Link>
组件进行页面跳转,避免直接修改 window.location
。
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
2. 编程式导航( useNavigate
)
通过 useNavigate
钩子实现动态跳转,适用于按钮点击或条件判断的场景。
import { useNavigate } from 'react-router-dom';
function Home() {
const navigate = useNavigate();
const handleClick = () => {
navigate('/about');
};
return (
<button onClick={handleClick}>跳转到 About</button>
);
}
三、路由参数与动态路由
1. 动态路由参数
使用 :param
语法定义动态路由参数,通过 useParams
获取参数。
<Route path="/user/:id" element={<User />} />
获取参数:
import { useParams } from 'react-router-dom';
function User() {
const { id } = useParams();
return <div>用户ID: {id}</div>;
}
2. 搜索参数
通过 useSearchParams
获取 URL 中的查询参数。
import { useSearchParams } from 'react-router-dom';
function SearchPage() {
const [searchParams, setSearchParams] = useSearchParams();
const query = searchParams.get('q');
return (
<div>搜索关键词: {query}</div>
);
}
四、嵌套路由
1. 定义嵌套路由
使用 <Outlet>
组件渲染子路由内容,搭配 <Route>
定义动态嵌套路径。
<Route path="/" element={<Layout />}>
<Route index element={<Home />} /> {/* 默认路由 */}
<Route path="about" element={<About />} />
<Route path="user/:id" element={<User />} />
</Route>
Layout
组件中渲染 <Outlet />
:
function Layout() {
return (
<div>
<Header />
<Outlet /> {/* 渲染子路由内容 */}
</div>
);
}
2. 动态嵌套路径
可以通过 useMatch
获取当前路由信息,实现动态嵌套路由逻辑。
import { useMatch } from 'react-router-dom';
function UserPage() {
const match = useMatch('/user/:id');
return <div>用户ID: {match.params.id}</div>;
}
五、路由守卫(导航守卫)
React Router v6 没有直接的 beforeRoute
、afterRoute
等守卫机制,但可以通过 useNavigate
配合条件判断实现基本的导航控制。
import { useNavigate } from 'react-router-dom';
function ProtectedRoute({ children }) {
const navigate = useNavigate();
const isAuthenticated = checkAuth(); // 自定义认证逻辑
if (!isAuthenticated) {
navigate('/login');
}
return children;
}
六、路由模式(Hash/History)
1. Hash 模式
在开发时,为了避免配置服务器支持 history
模式,可以使用 createHashRouter
,它基于 window.location.hash
实现。
import { createHashRouter } from 'react-router-dom';
const router = createHashRouter([
{ path: '/', element: <Home /> },
{ path: '/about', element: <About /> }
]);
export default router;
2. History 模式
若服务器已支持 history
模式,可以通过 createBrowserRouter
实现。
import { createBrowserRouter } from 'react-router-dom';
const router = createBrowserRouter([
{ path: '/', element: <Home /> },
{ path: '/about', element: <About /> }
]);
export default router;
七、常见问题
1. 路由匹配错误
- 确保路径分隔符使用
/
,避免空格或拼写错误。 - 确保
<Routes>
包裹所有路由,且<Route>
不能直接放在return
中。
2. 404 页面
- 使用
path="*"
匹配所有未定义的路径。
<Route path="*" element={<NotFound />} />
3. 嵌套路由渲染问题
- 确保父路由中包含
<Outlet />
来渲染子路由内容。 - 确保子路由路径不以
/
开头(否则会被视为绝对路径)。
v5 与 v6 的主要差异
特性 | React Router v5 | React Router v6 |
---|---|---|
路由容器 | <BrowserRouter> /<HashRouter> | <BrowserRouter> /<HashRouter> |
路由匹配 | <Switch> + <Route> | <Routes> + <Route> |
component | 保留 | 淘汰(改用 element ) |
动态路由参数 | match.params | params 钩子 |
程序化导航 | history.push() /<Redirect> | useNavigate() 钩子 |