react-router
React Router是一个用于构建单页面应用程序(SPA)的库,它是用于管理React应用中页面导航和路由的工具。SPA是一种Web应用程序类型,它在加载初始页面后,通过JavaScript来动态加载并更新页面内容,而不是在每次页面切换时都请求完整的新页面。通过React Router可以在React应用中实现客户端路由,在不刷新整个页面的情况下切换到不同的视图或页面。
React Router是由多个包组成的库,每个包都提供了不同的功能。以下是React Router主要的包:
-
react-router-dom:这是React Router的核心包,用于构建Web应用的路由。它包括了用于在浏览器中实现客户端路由的组件,如BrowserRouter、Route、Link等。大多数Web应用都会使用这个包来管理路由。
-
react-router-native:这个包是React Router的一个扩展,用于构建React Native应用的路由。它提供了类似于react-router-dom的API,但专门针对React Native环境进行了优化。
-
react-router(不带后缀):这是React Router的核心包,它包括了一些通用的路由功能,可以在Web和Native应用中使用。但在实际开发中,通常会使用react-router-dom或react-router-native,具体根据应用类型来选择。
除了上述主要的包,React Router还提供了一些辅助工具和附加功能的包:
-
react-router-config:这个包用于将路由配置信息提取到一个单独的地方,以便于静态路由渲染。这对于服务器渲染React应用非常有用。
-
react-router-redux:这个包用于与Redux集成,以便在Redux存储中管理路由状态。
-
@reach/router:虽然不是React Router的一部分,但它是一个与React Router兼容的替代品,提供了一些不同的API和性能特性。它专注于可访问性和无障碍性。
在大多数情况下,使用react-router-dom是构建Web应用的首选选择。
react-router-dom
react-router-dom提供了许多API,用于构建Web应用的客户端路由。以下是一些react-router-dom的主要API以及它们的简单示例用法:
- BrowserRouter:用于包装应用程序,启用基于浏览器的路由。
js
import { BrowserRouter, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</BrowserRouter>
);
}
- Route:用于定义路由匹配的路径和要渲染的组件。
js
import { Route } from 'react-router-dom';
function App() {
return (
<div>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</div>
);
}
- Link:用于创建导航链接。
js
import { Link } from 'react-router-dom';
function Navigation() {
return (
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</nav>
);
}
- Switch :用于包装多个
Route
,只渲染第一个匹配的路由。
js
import { Switch, Route } from 'react-router-dom';
function App() {
return (
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route component={NotFound} />
</Switch>
);
}
- Redirect:用于在路由重定向时进行配置。
js
import { Redirect } from 'react-router-dom';
function App() {
return (
<div>
<Switch>
<Route exact path="/" render={() => <Redirect to="/home" />} />
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
</Switch>
</div>
);
}
React Router DOM提供的自定义Hook
react-router-dom还提供了一些自定义Hook,用于在函数组件中访问路由相关信息。例如:
-
useHistory:
useHistory
Hook 允许你在组件中访问路由历史对象,以便进行编程式导航,例如在按钮点击或其他事件中跳转到不同的路由。jsimport { useHistory } from 'react-router-dom'; function MyComponent() { const history = useHistory(); const handleButtonClick = () => { // 编程式导航到'/about'路由 history.push('/about'); }; return ( <div> <button onClick={handleButtonClick}>Go to About</button> </div> ); }
-
useLocation:
useLocation
Hook 允许你访问当前路由的location
对象,包括路径、查询参数等信息。jsimport { useLocation } from 'react-router-dom'; function MyComponent() { const location = useLocation(); return ( <div> <p>Current Path: {location.pathname}</p> <p>Query Parameters: {location.search}</p> </div> ); }
-
useParams:
useParams
Hook 用于获取当前路由的动态路由参数。当你在路由定义中使用参数占位符时,你可以使用这个Hook来获取传递给路由的参数值。jsimport { useParams } from 'react-router-dom'; function UserProfile() { const { username } = useParams(); return ( <div> <h2>User Profile</h2> <p>Username: {username}</p> </div> ); }
参数传递
在react-router-dom中,你可以使用路由参数来传递和获取参数。参数通常用于将动态数据传递给组件,例如用户ID或产品ID。
-
定义带参数的路由:
首先,在路由配置中定义带有参数的路由。使用
:parameterName
来表示参数占位符。例如:jsx<Route path="/user/:userId" component={UserProfile} />
-
使用
useParams
Hook获取参数:在要接收参数的组件中,使用
useParams
Hook来获取参数的值。例如:jsimport { useParams } from 'react-router-dom'; function UserProfile() { const { userId } = useParams(); return ( <div> <h2>User Profile</h2> <p>User ID: {userId}</p> </div> ); }
在上面的示例中,使用
useParams
Hook来获取路由参数中的userId
。这个参数的值将根据实际的路由路径动态获取。 -
传递参数:
若要传递参数到带参数的路由,可以在
<Link>
组件或编程式导航中设置参数。例如:使用
<Link>
组件:jsimport { Link } from 'react-router-dom'; function UserList() { return ( <ul> <li><Link to="/user/1">User 1</Link></li> <li><Link to="/user/2">User 2</Link></li> {/* ... */} </ul> ); }
编程式导航:
jsimport { useHistory } from 'react-router-dom'; function navigateToUserProfile(userId) { const history = useHistory(); history.push(`/user/${userId}`); }
V5 和 V6的使用区别
<Switch>
全部改为<Routes>
javascript
// v5
import {Route, Switch} from 'react-router-dom' //引入react-router
<div>
<Switch>
</Switch>
</div>
// v6
import {Route, Routes } from 'react-router-dom' //引入react-router
<div>
<Routes >
</Routes>
</div>
- Route 的 render 和 component 改为 element,且可以嵌套路由
javascript
// v5
import {Route, Switch} from 'react-router-dom' //引入react-router
<div>
<Switch>
<Route path="/about">
<About />
</Route>
</Switch>
</div>
// v6
import {Route, Routes } from 'react-router-dom' //引入react-router
<div>
<Routes >
<Route path="/about" element={<About />} />
</Routes>
</div>
-
to、navigate、path 不以 / 开头都是相对路径,与 cd 命令行类似
在 v5 中,以 / 开头的
<Link to>
值是不明确的;它取决于当前的 URL 是什么。例如,如果当前的 URL 是 /users ,那么 v5 中的 将呈现为<a href="/me">
。然而,如果当前的 URL 有一个尾随斜杠,比如 /users/ ,同样的 将呈现为<a href="/users/me">
。这使得很难预测链接的行为,因此在 v5 中,从根 URL(使用 match.url )构建链接,而不是使用相对的<Link to>
值。React Router v6 修复了这种不确定性。在 v6 中,无论当前的 URL 是什么,
<Link to="me">
都将始终呈现相同的<a href>
。例如,在
<Route path="users">
中呈现的<Link to="me">
将始终呈现到 /users/me 的链接,无论当前的 URL 是否有尾随斜杠。 -
v6 用useNavigate实现编程式导航,不再使用useHistory
naviaget(to)默认就是 history.push,naviaget(to, { replace: true })就是 history.replace,naviaget(to: number)就是 history.go。
javascript
import { useNavigate } from "react-router-dom";
function App() {
const navigate = useNavigate();
function handleClick() {
navigate("/home");
}
return (
<div>
<button onClick={handleClick}>go home</button>
</div>
);
}