路由组件
在 React Router 中,路由组件是用于定义应用中不同页面或视图的组件。它们决定了用户访问特定 URL 时应该显示的内容。随着 React Router 的版本更新,API 和推荐的用法也有所变化。以下是基于最新版 React Router v6 的介绍,涵盖了主要的路由组件及其使用方法。
主要路由组件
1. <BrowserRouter> (或 <HashRouter>, <MemoryRouter>)
这是最外层的路由容器组件,它为应用提供了一个路由环境。根据你的需求选择不同的路由器:
<BrowserRouter>:使用 HTML5 History API (pushState,replaceState) 来管理浏览器历史记录。<HashRouter>:使用 URL 的哈希部分 (#) 来模拟页面变化。<MemoryRouter>:将历史状态保存在内存中,适用于非浏览器环境。
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Router>
);
}2. <Routes>
<Routes> 是一个逻辑组件,它负责匹配当前 URL 并渲染对应的 <Route>。它是 v6 版本中的新特性,取代了旧版本中的 <Switch> 组件。<Routes> 使用更严格的匹配规则,确保只有一个 <Route> 被渲染(除非明确指定了 element 属性)。
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>3. <Route>
<Route> 定义了 URL 模式和相应的组件之间的映射关系。每个 <Route> 都有一个 path 属性来指定 URL 模式,以及一个 element 属性来指定要渲染的 React 组件。
动态路径参数
你可以通过在路径中添加冒号(:paramName)来定义动态路径参数,并在组件内部使用 useParams Hook 获取这些参数。
<Route path="/user/:id" element={<User />} />嵌套路由
React Router v6 支持嵌套路由,即一个路由可以包含其他路由。这使得构建复杂的应用结构变得非常容易。
<Route path="users" element={<Users />}>
<Route index element={<AllUsers />} />
<Route path=":userId" element={<UserProfile />} />
</Route>精确匹配
默认情况下,<Route> 会尝试尽可能精确地匹配路径。如果你想要强制完全匹配,可以使用 path="exact",但通常不需要这样做,因为 <Routes> 已经实现了严格的匹配规则。
标签属性
1. path (v5, v6)
- 类型:字符串或
- 说明:定义路径模式。可以是一个单独的字符串或者。
- 类型:React Component
- 说明:指定要渲染的组件。当路径匹配时,此组件会被渲染,并且会接收到
match,location, 和history作为 props。
- 类型:函数
- 说明:接收一个返回 JSX 的函数,允许你在渲染之前执行逻辑。该函数会接收到
match,location, 和history作为参数。
- 类型:JSX.Element
- 说明:指定要渲染的 React 元素。替代了
v5中的component和render属性。使用时直接传入 JSX 表达式。
5. children (v5, v6)
- 类型:React Node、、
6. exact (v5, v6)
- 类型:布尔值
- 类型:布尔值
- 说明:在匹配路径时,严格区分尾部斜杠。默认情况下,
/one也会匹配/one/,但如果设置了strict={true},则不会。
- 类型:布尔值
- 说明:使路径匹配对大小写敏感。默认情况下,路径匹配不区分大小写。
9. location (v5, v6)
- 类型:对象
- 说明:自定义要匹配的位置对象。这在某些特定场景下很有用,例如测试或嵌套路由。
- 类型:布尔值
- 说明:表示这是一个索引路由。当父级路由被访问但没有更具体的子路由匹配时,会渲染此路由。
- 类型:布尔值
- 说明:使路径匹配对大小写敏感,默认是不区分大小写的。
- 类型:函数
- 说明:一个异步函数,用于在加载页面之前获取数据。这是
v6引入的新特性,支持数据预取和加载状态管理。
- 类型:JSX.Element
- 说明:指定当
loader函数抛出错误时渲染的元素。这有助于处理加载过程中可能出现的异常情况。
4. <Link> 和 <NavLink>
这两个组件用于创建导航链接,使用户能够在不同页面之间切换而不刷新整个页面。
<Link>:普通的导航链接。<NavLink>:带有激活样式(如activeClassName或style)的导航链接。
标签属性:
4.1. to
- 类型:字符串或对象
- 描述:指定要导航的目标路径。可以是一个字符串形式的 URL 或者一个包含路径和其他选项的对象。
- 字符串:例如
"/home"或"/users/123". - 对象:
pathname:目标路径。search:查询参数(作为字符串)。hash:锚点(例如#section1)。state:附加的状态信息(仅适用于编程式导航)。
- 字符串:例如
<Link to="/about">About</Link>
<Link to={{ pathname: '/profile', search: '?name=John', hash: '#bio' }}>Profile</Link>4.2. replace
- 类型:布尔值
- 描述:如果设置为
true,则当前条目将被替换而不是添加到浏览器的历史记录栈中。这意味着用户不能通过“后退”按钮返回到之前的页面。
<Link to="/settings" replace>
Settings
</Link>4.3. state
- 类型:任意类型
- 描述:传递给目标路由的额外状态信息。这个状态不会出现在 URL 中,而是通过
useLocation().state在目标组件中访问。
<Link to="/details" state={{ fromDashboard: true }}>
Details
</Link>
- 类型:函数或 Ref 对象
- 描述:用于获取对底层 DOM 元素的引用。你可以使用
React.createRef()或useRef钩子来创建 ref,并将其传递给innerRef属性。
const linkRef = useRef(null);
// ...
<Link innerRef={linkRef}>My Link</Link>;4.5. className 和 style
- 类型:字符串(对于
className)或对象(对于style) - 描述:用于自定义
<Link>组件的样式。className可以接受一个或多个 CSS 类名,而style接受内联样式对象。
<Link className="nav-link" style={{ color: "blue" }}>
Home
</Link>
- 类型:字符串(对于
activeClassName)或对象(对于activeStyle) - 描述:当链接与当前活动的路由匹配时应用的类名或样式。这对于高亮显示当前选中的导航项非常有用。
<Link to="/home" activeClassName="active">
Home
</Link>
- 类型:布尔值
- 描述:确保只有当路径完全匹配时才应用
activeClassName或activeStyle。这在处理嵌套路由时特别有用。
<Link to="/" exact activeClassName="active">
Home
</Link>
- 类型:布尔值
- 描述:当设置为
true时,要求路径严格匹配,包括尾部斜杠。默认情况下,路径/home和/home/是被视为相同的。
<Link to="/home" strict activeClassName="active">
Home
</Link>4.9. onClick
- 类型:函数
- 描述:点击链接时触发的事件处理器。请注意,如果你在这个事件处理器中执行任何操作(如阻止默认行为),你需要调用
event.preventDefault()来防止页面跳转。
<Link
to="/about"
onClick={(e) => {
e.preventDefault();
console.log("Clicked!");
}}
>
About
</Link>import { Link, NavLink } from "react-router-dom";
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<NavLink to="/about" activeClassName="selected">
About
</NavLink>
</li>
<li>
<NavLink to="/contact" activeClassName="selected">
Contact
</NavLink>
</li>
</ul>
</nav>;
- 如果你想要确保只有当 URL 完全匹配时才认为是活动状态,可以使用
end属性。这相当于以前版本中的exact。
<NavLink to="/home" end>
Home
</NavLink>
- 在
NavLink中,你可以传递一个回调函数给className属性,该函数接收一个对象参数{ isActive, isPending },可以根据是否激活来自定义类名。
<NavLink
to="/about"
className={({ isActive }) => (isActive ? "active-link" : "inactive-link")}
>
About
</NavLink>5. 导航和重定向
<Navigate>:用于实现编程式的导航或重定向。它可以替代旧版本中的<Redirect>组件。
<Route path="/old-path" element={<Navigate to="/new-path" />} />useNavigateHook:用于在组件内执行编程式的导航操作。
import { useNavigate } from "react-router-dom";
function GoBackButton() {
const navigate = useNavigate();
return <button onClick={() => navigate(-1)}>Go Back</button>;
}示例代码
以下是一个完整的例子,展示了如何结合上述组件来构建一个简单的单页应用:
import React from "react";
import {
BrowserRouter as Router,
Route,
Routes,
Link,
Navigate,
} from "react-router-dom";
const Home = () => <h2>Home</h2>;
const About = () => <h2>About</h2>;
const Contact = () => <h2>Contact</h2>;
const User = ({ match }) => <h2>User Profile: {match.params.id}</h2>;
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
<li>
<Link to="/user/123">User 123</Link>
</li>
</ul>
</nav>
{/* Render the appropriate component based on the current URL */}
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
<Route path="/user/:id" element={<User />} />
{/* Redirect old paths */}
<Route path="/old-about" element={<Navigate to="/about" />} />
</Routes>
</div>
</Router>
);
}
export default App;总结
React Router 提供了一套强大且灵活的 API 来处理单页应用中的路由管理。通过理解并正确使用这些路由组件,你可以轻松地构建出功能丰富、用户体验良好的应用程序。