深入理解 React Router

React Router:单页面应用中的路由解决方案

React Router 是 React 生态中最流行的路由解决方案之一,它让单页面应用(SPA)的路由管理变得简单高效。通过 React Router,你可以轻松地管理应用中的不同视图和页面,同时保持用户体验的一致性和流畅性。

一、路由实现的界面效果

导航栏/侧边栏保持不刷新

  • 效果:切换路由时,顶部导航、侧边菜单等公共部分保持不动
  • 实现 :将共享布局放在父路由的 element
js 复制代码
import { Routes, Route } from 'react-router-dom';
import Layout from './components/Layout';
import Dashboard from './pages/Dashboard';
import Users from './pages/Users';

function App() {
  return (
    <Routes>
      <Route path="/admin" element={<Layout />}>
        {/* 子路由内容变化,Layout保持不刷新 */}
        <Route index element={<Dashboard />} />
        <Route path="users" element={<Users />} />
      </Route>
    </Routes>
  );
}

在这个例子中,Layout 组件包含了导航栏和侧边栏等公共部分。无论用户访问 /admin 还是 /admin/usersLayout 组件都不会重新渲染,只有其内部的内容会根据子路由的变化而变化。

内容区域动态刷新

  • 效果:只有主要内容区域随路由变化
  • 实现 :在布局组件中使用 <Outlet />
js 复制代码
// Layout.js
import { Outlet } from 'react-router-dom';

function Layout() {
  return (
    <div>
      <header>
        <h1>My Admin Panel</h1>
        <nav>
          <ul>
            <li><a href="/admin">Dashboard</a></li>
            <li><a href="/admin/users">Users</a></li>
          </ul>
        </nav>
      </header>
      <main>
        <Outlet /> {/* 子路由的内容会在这里渲染 */}
      </main>
    </div>
  );
}

export default Layout;

<Outlet /> 是一个占位符,用于渲染当前匹配的子路由的内容。这样,当用户从 /admin 切换到 /admin/users 时,只有 <Outlet /> 中的内容会发生变化,而 Layout 组件的其他部分保持不变。

无刷新跳转(保持滚动位置)

  • 效果:切换路由时页面不会闪烁,滚动条位置保持不变
  • 原理:React Router 默认使用客户端路由(不触发整页刷新)

由于 React Router 使用的是客户端路由,页面不会重新加载,因此滚动位置和其他状态信息会被保留。这使得用户在导航过程中体验更加平滑。

二、路由基本结构

在组件中使用 <Routes><Route> 定义路由结构:

  • <Routes> :包裹所有路由规则的容器,负责匹配当前URL并渲染对应的组件

  • <Route> :定义单个路由规则

    • path:匹配的URL路径
    • element:匹配时要渲染的组件
    • index:标识默认子路由
  • 嵌套路由 :通过嵌套<Route>实现布局共享

js 复制代码
import { Routes, Route } from 'react-router-dom';
import Login from './views/login/index';
import MainLayout from './views/layout/index';
import Home from './views/home/index';
import Public from './views/public/index';
import Score from './views/score/index';

function App() {
  return (
    <Routes>
      <Route path="/login" element={<Login />} />
      <Route path="/layout" element={<MainLayout />}>
        <Route index element={<Home />} />
        <Route path="public" element={<Public />} />
        <Route path="score" element={<Score />} />
      </Route>
    </Routes>
  );
}

在这个例子中,/layout 路径下的所有子路由都会使用 MainLayout 作为布局组件。具体来说:

  • 访问 /layout 时,显示 MainLayout 框架 + Home 内容。
  • 访问 /layout/public 时,显示 MainLayout 框架 + Public 内容。
  • 访问 /layout/score 时,显示 MainLayout 框架 + Score 内容。

<Route index element={<Home />} /> 表示当用户访问 /layout 路径时,默认渲染 Home 组件。

三、useNavigate - 编程式导航

有时候需要在代码逻辑中进行导航,而不是通过点击链接来触发导航。这时可以使用 useNavigate 钩子。

js 复制代码
import { useNavigate } from 'react-router-dom';

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

  const handleLogin = () => {
    // 基本跳转
    navigate('/dashboard');
  };
  return <button onClick={handleLogin}>Login</button>;
}

在这个例子中,当用户点击"Login"按钮时,应用会导航到 /dashboard 路径。 假设当前位置为 http://localhost:3000,调用 LoginButton 后会自动跳转到 http://localhost:3000/dashboard

带参数的导航

js 复制代码
import { useNavigate } from 'react-router-dom';

function ProductPage({ productId }) {
  const navigate = useNavigate();

  const goToProductDetail = () => {
    navigate(`/products/${productId}`);
  };

  return (
    <div>
      <h1>Product Page</h1>
      <button onClick={goToProductDetail}>View Details</button>
    </div>
  );
}

在这个例子中,navigate 函数可以接受路径参数,从而导航到具体的商品详情页面。请

四、动态路由参数

有时需要在 URL 中传递参数,以便在目标组件中获取这些参数并进行相应的操作。React Router 支持动态路由参数。

定义动态参数

js 复制代码
<Route path="/products/:id" element={<ProductDetail />} />

在这个例子中,:id 是一个动态参数,表示产品 ID。

获取动态参数

js 复制代码
import { useParams } from 'react-router-dom';

function ProductDetail() {
  const { id } = useParams();
  // 使用id获取产品数据...

  return (
    <div>
      <h1>Product Detail</h1>
      <p>Product ID: {id}</p>
    </div>
  );
}

在这个例子中,useParams 钩子用于获取 URL 中的动态参数 id,然后可以在组件中使用这个参数来获取或显示相应的产品数据。

相关推荐
知了清语21 分钟前
pnpm之monorepo项目, vite版本冲突, 导致vite.config.ts ts警告处理
前端
弗锐土豆44 分钟前
一个基于若依(ruoyi-vue3)的小项目部署记录
前端·vue.js·部署·springcloud·ruoyi·若依
Hilaku1 小时前
我为什么放弃了“大厂梦”,去了一家“小公司”?
前端·javascript·面试
1undefined21 小时前
element中的table改造成虚拟列表(不定高),并封装成hooks
前端·vue.js
浅墨momo1 小时前
搭建第一个Shopify App
前端·程序员
然我1 小时前
React 事件机制:从代码到原理,彻底搞懂合成事件的核心逻辑
前端·react.js·面试
Codebee1 小时前
OneCode 组件服务通用协议栈:构建企业级低代码平台的技术基石
前端·前端框架·开源
Running_C1 小时前
常见web攻击类型
前端·http
jackyChan1 小时前
ES6 Proxy 性能问题,你真知道吗?🚨
前端·javascript