Skip to content

路由组件

React Router 中,路由组件是用于定义应用中不同页面或视图的组件。它们决定了用户访问特定 URL 时应该显示的内容。随着 React Router 的版本更新,API 和推荐的用法也有所变化。以下是基于最新版 React Router v6 的介绍,涵盖了主要的路由组件及其使用方法。

主要路由组件

1. <BrowserRouter> (或 <HashRouter>, <MemoryRouter>)

这是最外层的路由容器组件,它为应用提供了一个路由环境。根据你的需求选择不同的路由器:

  • <BrowserRouter>:使用 HTML5 History API (pushState, replaceState) 来管理浏览器历史记录。
  • <HashRouter>:使用 URL 的哈希部分 (#) 来模拟页面变化。
  • <MemoryRouter>:将历史状态保存在内存中,适用于非浏览器环境。
jsx
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 属性)。

jsx
<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 获取这些参数。

jsx
<Route path="/user/:id" element={<User />} />

嵌套路由

React Router v6 支持嵌套路由,即一个路由可以包含其他路由。这使得构建复杂的应用结构变得非常容易。

jsx
<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 中的 componentrender 属性。使用时直接传入 JSX 表达式。
5. children (v5, v6)
  • 类型:React Node、
6. exact (v5, v6)
  • 类型:布尔值
  • 类型:布尔值
  • 说明:在匹配路径时,严格区分尾部斜杠。默认情况下,/one 也会匹配 /one/,但如果设置了 strict={true},则不会。
  • 类型:布尔值
  • 说明:使路径匹配对大小写敏感。默认情况下,路径匹配不区分大小写。
9. location (v5, v6)
  • 类型:对象
  • 说明:自定义要匹配的位置对象。这在某些特定场景下很有用,例如测试或嵌套路由。
  • 类型:布尔值
  • 说明:表示这是一个索引路由。当父级路由被访问但没有更具体的子路由匹配时,会渲染此路由。
  • 类型:布尔值
  • 说明:使路径匹配对大小写敏感,默认是不区分大小写的。
  • 类型:函数
  • 说明:一个异步函数,用于在加载页面之前获取数据。这是 v6 引入的新特性,支持数据预取和加载状态管理。
  • 类型:JSX.Element
  • 说明:指定当 loader 函数抛出错误时渲染的元素。这有助于处理加载过程中可能出现的异常情况。

这两个组件用于创建导航链接,使用户能够在不同页面之间切换而不刷新整个页面。

  • <Link>:普通的导航链接。
  • <NavLink>:带有激活样式(如 activeClassNamestyle)的导航链接。

标签属性:

4.1. to

  • 类型:字符串或对象
  • 描述:指定要导航的目标路径。可以是一个字符串形式的 URL 或者一个包含路径和其他选项的对象。
    • 字符串:例如 "/home""/users/123".
    • 对象
      • pathname:目标路径。
      • search:查询参数(作为字符串)。
      • hash:锚点(例如 #section1)。
      • state:附加的状态信息(仅适用于编程式导航)。
jsx
<Link to="/about">About</Link>
<Link to={{ pathname: '/profile', search: '?name=John', hash: '#bio' }}>Profile</Link>

4.2. replace

  • 类型:布尔值
  • 描述:如果设置为 true,则当前条目将被替换而不是添加到浏览器的历史记录栈中。这意味着用户不能通过“后退”按钮返回到之前的页面。
jsx
<Link to="/settings" replace>
  Settings
</Link>

4.3. state

  • 类型:任意类型
  • 描述:传递给目标路由的额外状态信息。这个状态不会出现在 URL 中,而是通过 useLocation().state 在目标组件中访问。
jsx
<Link to="/details" state={{ fromDashboard: true }}>
  Details
</Link>

  • 类型:函数或 Ref 对象
  • 描述:用于获取对底层 DOM 元素的引用。你可以使用 React.createRef()useRef 钩子来创建 ref,并将其传递给 innerRef 属性。
jsx
const linkRef = useRef(null);
// ...
<Link innerRef={linkRef}>My Link</Link>;

4.5. classNamestyle

  • 类型:字符串(对于 className)或对象(对于 style
  • 描述:用于自定义 <Link> 组件的样式。className 可以接受一个或多个 CSS 类名,而 style 接受内联样式对象。
jsx
<Link className="nav-link" style={{ color: "blue" }}>
  Home
</Link>

  • 类型:字符串(对于 activeClassName)或对象(对于 activeStyle
  • 描述:当链接与当前活动的路由匹配时应用的类名或样式。这对于高亮显示当前选中的导航项非常有用。
jsx
<Link to="/home" activeClassName="active">
  Home
</Link>

  • 类型:布尔值
  • 描述:确保只有当路径完全匹配时才应用 activeClassNameactiveStyle。这在处理嵌套路由时特别有用。
jsx
<Link to="/" exact activeClassName="active">
  Home
</Link>

  • 类型:布尔值
  • 描述:当设置为 true 时,要求路径严格匹配,包括尾部斜杠。默认情况下,路径 /home/home/ 是被视为相同的。
jsx
<Link to="/home" strict activeClassName="active">
  Home
</Link>

4.9. onClick

  • 类型:函数
  • 描述:点击链接时触发的事件处理器。请注意,如果你在这个事件处理器中执行任何操作(如阻止默认行为),你需要调用 event.preventDefault() 来防止页面跳转。
jsx
<Link
  to="/about"
  onClick={(e) => {
    e.preventDefault();
    console.log("Clicked!");
  }}
>
  About
</Link>
jsx
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
jsx
<NavLink to="/home" end>
  Home
</NavLink>

  • NavLink 中,你可以传递一个回调函数给 className 属性,该函数接收一个对象参数 { isActive, isPending },可以根据是否激活来自定义类名。
jsx
<NavLink
  to="/about"
  className={({ isActive }) => (isActive ? "active-link" : "inactive-link")}
>
  About
</NavLink>

5. 导航和重定向

  • <Navigate>:用于实现编程式的导航或重定向。它可以替代旧版本中的 <Redirect> 组件。
jsx
<Route path="/old-path" element={<Navigate to="/new-path" />} />
  • useNavigate Hook:用于在组件内执行编程式的导航操作。
jsx
import { useNavigate } from "react-router-dom";

function GoBackButton() {
  const navigate = useNavigate();

  return <button onClick={() => navigate(-1)}>Go Back</button>;
}

示例代码

以下是一个完整的例子,展示了如何结合上述组件来构建一个简单的单页应用:

jsx
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 来处理单页应用中的路由管理。通过理解并正确使用这些路由组件,你可以轻松地构建出功能丰富、用户体验良好的应用程序。

Released under the MIT License.