带你使用 React 路由 react-router-dom v6

前言

在浏览器中页面的跳转是根据地址栏 url 的变化的,从一个页面跳转到另一个页面,这个是属于多页面应用(MPA)。除了多页面,还有另一种情况,单页面应用(SPA)。

单页面应用只有一个完整的页面,url 的变化不会刷新页面,而是页面内容的局部变化。

路由

在 React 项目中路由也是较为重要的部分,我们可以用它来管理 URL,实现页面组件切换。在 router v6相比之前的 v3、v4、v5版本,v6吸收了之前版本的经验并进行了改进,相对于之前一些方法、属性也不尽相同,也相对复杂了一点。

使用

我们可以去安装 react-router-dom,它专门在 react 项目中实现一个 SPA 应用。

npm i react-router-dom

安装完成后查看 package.json 文件可以看到

上图可以看到安装的是 router v6 版本, v6 版本跟 v5 版本有些差异,移除了一些组件和修改一些属性,接下来使用和介绍的都是 v6 版本的

例子

index.js

React 的路由的实现有两种:一种是 browser history ------ <BrowserRouter>,一种是 hash history ------<HashRouter>

从 react-router-dom 导入 BrowserRouter 组件,用来包裹 App 组件。

js 复制代码
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
      <BrowserRouter>
        <App />
      </BrowserRouter>
  </React.StrictMode>
);

App.js

  • NavLink ,该组件可以根据 to 属性跳转对应路由组件
  • Routes ,和 Route 配合使用,用来包裹 Route 组件
  • Route ,根据 element 属性传入的组件,给组件匹配于 path 值,当其路径与当前 path 值匹配时,则呈现该传入的组件
  • Navigate,只要被渲染,就会修改路径,切换视图
js 复制代码
// App.js
import { NavLink, Routes, Route, Navigate } from 'react-router-dom';
import Home from "./pages/home/home"
import My from "./pages/my/my"

function App() {
  return (
    <div>
      <ul>
        <li>
          <NavLink to="/home">Home</NavLink>
        </li>
        <li>
          <NavLink to="/my">my</NavLink>
        </li>
      </ul>
      <Routes>
        <Route path="/home" element={<Home />}></Route>
        <Route path="/my" element={<My />}></Route>
        <Route path="/" element={<Navigate to="/home" />}></Route>
      </Routes>
    </div>
  );
}
export default App

home.js 创建 home 路由组件

js 复制代码
function Home(props) {
  return (
    <div>
      <p>Hello, home!</p>
    </div>
  );
}
export default Home

my.js 创建 my 路由组件

js 复制代码
function My() {
  return (
    <div>
      <p>Hello, my!</p>
    </div>
  );
}
export default My

这样我们就可以实现一个简单的路由切换了

路由表

其中这一段代码可以抽离出来,制定路由表

js 复制代码
<Routes>
    <Route path="/home" element={<Home />}></Route>
    <Route path="/my" element={<My />}></Route>
    <Route path="/" element={<Navigate to="/home" />}></Route>
</Routes>

创建 routers 文件夹 ,新建 index.js 文件

js 复制代码
import { Navigate } from "react-router-dom"
import Home from '../pages/home/home'
import My from '../pages/my/my'

export const router = [
  {
    path: '/home',
    element: <Home />
  },
  {
    path: '/my',
    element: <My />
  },
  {
    path: '/',
    element: <Navigate to="/home" />
  },
]

使用路由表,在其中需要调用 useRoutes 并传入已经配置好的路由表,生成相当于 routes 以及 route 的组件结构,可以直接利用 {} 去进行包裹使用

js 复制代码
// App.js
import { NavLink, useNavigate, useRoutes } from 'react-router-dom';
import { routers } from './routers'

// 根据路由表生成对应的路由规则
const element = useRoutes(routers)

// 直接在 dom 结构中使用
{element}

路由跳转

js 复制代码
import { Link } from 'react-router-dom';
<Link to="/my">Link</Link>
js 复制代码
import { NavLink } from "react-router-dom"; 
<NavLink to="/my">my</NavLink>

useNavigate 钩子函数

调用 useNavigate 函数去获得 navigate,传入路由 path 就可以切换到对应路由

js 复制代码
import { // BrowserRouter, useNavigate, } from "react-router-dom";
const navigate = useNavigate(); 
navigate("/my");

参数传递

当我们进行路由跳转的时候需要携带一些参数,然后去到另一个路由利用参数进行一些操作,像一些跳转到详情页,传递的就是文章的id值,利用这id值查询出相应的数据等等情景。传参的方法有 params、search这几种。

params

在url后面拼接参数,进行动态传参,显示在地址栏上,刷新页面后参数不丢失

js 复制代码
// 路由配置
{
  path: '/my/:id',
  element: <My />
},

// 路由跳转
<li>
  <NavLink to="/my/18">my</NavLink>
</li>

// 路由组件接收,使用 useParams
import { useParams } from 'react-router-dom';
function My() {
  let params = useParams()
  console.log(params)
  return (
    <div>
      <p>Hello, my!</p>
    </div>
  );
}
export default My

由 useParams 获取到路由跳转传递的参数

?

可选参数,代表该参数可传可不传,不传的话也不会报错。

通常来说一旦url寻找不到对应路由地址会发生错误,从而渲染不出该组件。

js 复制代码
// 路由配置
{
  path: '/my/:id?',
  element: <My />
},
* 通配符

可以在后面匹配任何字符

js 复制代码
// 路由配置
{
  path: '/my/*',
  element: <My />
},

在url后面用 ? 拼接参数,参数形式使用 key=value 方式,多个参数使用 & 进行拼接,进行动态传参,显示在地址栏上,刷新页面后参数不丢失

js 复制代码
// 路由跳转,不用更改路由表
<li>
  <NavLink to="/my?age=18&name=小明">my</NavLink>
</li>

// 路由组件接收参数 useSearchParams
import { useSearchParams } from 'react-router-dom';
function My() {
  let [search] = useSearchParams()
  let age = search.get("age")
  let name = search.get("name")
  console.log(search, age, name)
  return (
    <div>
      <p>Hello, my!</p>
    </div>
  );
}
export default My

二级路由通过 useSearchParams 接收到的数据如下

路由嵌套

在有一些功能中,往往请求地址的前缀是相同的,不同的只是后面一部份,此时就可以使用多级路由(路由嵌套)来实现此路由的定义实现。

在一级路由定义 children 数组,里面用于配置二级路由,也就是进行路由嵌套。

js 复制代码
// 配置
const router = [
  {
    path: '/home',
    element: <Home />,
    children: [
      {
        path: 'header',
        element: <Header />
      }
    ]
  },
  {
    path: '/my',
    element: <My />
  },
  {
    path: '/',
    element: <Navigate to="/home" />
  },
]

要注意的是在一级路由组件里需要有<Outlet />去进行占位,在页面排放位置。

js 复制代码
// home.js home路由使用
import { Outlet } from 'react-router-dom';
function Home() {
  
  return (
    <div>
      {/* 嵌套路由出口 */}
      <Outlet />
      <p>Hello, home!</p>
    </div>
  );
}
export default Home

总结

优点

  • 加快页面响应速度,降低了对服务器的压力,因为单页应用只有第一次会加载完整的页面,切换内容只需请求该内容的数据,不用重新请求完整的页面

  • 更好的用户体验,运行更加流畅,因为局部的更新请求的资源少,加载速度快

缺点

  • 不利于 SEO ,因为 SEO 是根据首次请求的页面进行排名的,当路由的切换是监测不到的
  • 因为是单页面应用,所以初次渲染首屏加载的内容会比较多,加载较慢
相关推荐
For. tomorrow2 分钟前
Vue3中el-table组件实现分页,多选以及回显
前端·vue.js·elementui
布瑞泽的童话29 分钟前
无需切换平台?TuneFree如何搜罗所有你爱的音乐
前端·vue.js·后端·开源
白鹭凡42 分钟前
react 甘特图之旅
前端·react.js·甘特图
2401_862886781 小时前
蓝禾,汤臣倍健,三七互娱,得物,顺丰,快手,游卡,oppo,康冠科技,途游游戏,埃科光电25秋招内推
前端·c++·python·算法·游戏
书中自有妍如玉1 小时前
layui时间选择器选择周 日月季度年
前端·javascript·layui
Riesenzahn1 小时前
canvas生成图片有没有跨域问题?如果有如何解决?
前端·javascript
f8979070701 小时前
layui 可以使点击图片放大
前端·javascript·layui
忘不了情1 小时前
左键选择v-html绑定的文本内容,松开鼠标后出现复制弹窗
前端·javascript·html
世界尽头与你1 小时前
HTML常见语法设计
前端·html