当前位置: 首页 > news >正文

无废话、光速上手 React-Router

在这里插入图片描述

React-Router

React Router 是一个用于 React 应用的声明式路由库。它允许开发者通过组件化的方式定义应用的路由结构,使得路由管理更加直观和可维护

安装

pnpm i react-router-dom

定义路由

定义路由有两种方式,分别是对象路由和路由组件,下面将逐步介绍这两种方式的用法

两种方式

对象路由

对象路由通过 createBrowserRouter 数组中的每一项来定义,该方式适合复杂的情况下使用

import ReactDOM from 'react-dom/client';
import { createBrowserRouter, RouterProvider } from 'react-router-dom'function Home() {return (<><h1>Home</h1></>)
}function Cate() {return (<><h1>Cate</h1></>)
}// 核心代码
const router = createBrowserRouter([{// 路由访问路径path: "/",// 对应的页面组件element: <Home />},{path: "/cate",element: <Cate />}
])const root = ReactDOM.createRoot(document.getElementById('root')!);// 使用路由                                 
root.render(<RouterProvider router={router}></RouterProvider>
);
组件路由

直接通过组件来定义路由,这种方式适合简单的情况下使用

import ReactDOM from 'react-dom/client';
import { BrowserRouter, Route, Routes } from 'react-router-dom'function Home() {return (<><h1>Home</h1></>)
}function Cate() {return (<><h1>Cate</h1></>)
}const root = ReactDOM.createRoot(document.getElementById('root')!);root.render(<BrowserRouter><Routes><Route path="/" element={<Home />} /><Route path="/cate" element={<Cate />} /></Routes></BrowserRouter>
);

嵌套路由

当多个页面需要使用相同组件时,比如网站导航栏和底部,这两个组件通常会出现在所有页面当中,而这些公共组件我们没必要在多个页面单独引入,所以就需要用到嵌套路由

对象路由

import ReactDOM from 'react-dom/client';
import { createBrowserRouter, Outlet, RouterProvider } from 'react-router-dom'// 布局路由
function Layout() {return (<><div>这是一个通用导航栏组件</div>{/* 核心:这里一定要加 Outlet 否则无法显示子路由 */}<Outlet /><div>这是一个通用底部组件</div></>)
}function Home() {return (<><h1>Home</h1></>)
}function Cate() {return (<><h1>Cate</h1></>)
}function Login() {return (<><h1>Login</h1></>)
}const router = createBrowserRouter([{path: "/",element: <Layout />,children: [{// 定义为默认路由:当访问 / 时,会显示 Home 组件index: true,element: <Home />},{path: "/cate",element: <Cate />}]},{path: "/login",element: <Login />}
])const root = ReactDOM.createRoot(document.getElementById('root')!);root.render(<RouterProvider router={router}></RouterProvider>
);

组件路由

<BrowserRouter><Routes><Route path="/" element={<Layout />}><Route index element={<Home />} /><Route path="/cate" element={<Cate />} /></Route>{/* <Route element={<Layout />}><Route path="/" element={<Home />} /><Route path="/cate" element={<Cate />} /></Route> */}<Route path="/login" element={<Login />} /></Routes>
</BrowserRouter>

404 路由

当访问一个不存在的页面时会匹配到我们自定义的 404 路由

// 404页
function NotFound() {return (<><h1>404:页面未找到</h1></>)
}const router = createBrowserRouter([...,{path: "*",element: <NotFound />}
])
<BrowserRouter><Routes>...<Route path="*" element={<NotFound />} /></Routes>
</BrowserRouter>

动态路由

通常应用于通过 id 获取接口中对应的数据

const router = createBrowserRouter([// 单个:/cate/100{path: "/cate/:id",element: <Cate />},// 多个:/cate/100/200{path: "/cate/:one/:two",element: <Cate />},// 可选:/cate 或 /cate/100{path: "/cate/:id?",element: <Cate />},// 无限:/cate/100/200/300/400/500{path: "/cate/*",element: <Cate />}
])
<BrowserRouter><Router><Routes>{/* 路由组件不支持可选方式,但可以这样实现同样的效果 */}<Route path="/cate" element={<Cate />} /><Route path="/cate/:id" element={<Cate />} /><Route path="/cate/:one/:two" element={<Cate />} /><Route path="/cate/*" element={<Cate />} /></Routes></Router>
</BrowserRouter>

获取动态路由数据

通过 useParams() 来获取动态路由的参数数据

function Cate() {const params = useParams();return (<><h1>Cate</h1><pre>{JSON.stringify(params)}</pre></>);
}

访问:/cate/100/200

结果:{"one":"100","two":"200"}

路由跳转

通过 Link 进行路由跳转,其实它的本质还是通过 a 标签进行跳转的

<Link to="/cate">跳转</Link>
{/* 最终会编译成 */}
<a href="/cate">跳转</a>

声明式跳转

function Layout() {return (<><div>这是一个通用导航栏组件</div><Outlet /><div>这是一个通用底部组件</div></>)
}function Home() {return (<><h1>Home</h1><Link to="/cate">跳转到分类页</Link><Link to="/cate/100">跳转到分类页(带参数)</Link></>)
}function Cate() {return (<><h1>Cate</h1><Link to="/">跳转到首页</Link></>);
}const router = createBrowserRouter([{path: "/",element: <Layout />,children: [{index: true,element: <Home />},{path: "/cate/:id?",element: <Cate />}]}
])

编程式跳转

更多关于 useNavigate 的用法请见下方 API 目录

import { ..., useNavigate } from 'react-router-dom'function Home() {const navigator = useNavigate()return (<><h1>Home</h1><div onClick={() => navigator("/cate")}>跳转到分类页</div><button onClick={() => navigator("/cate/100")}>跳转到分类页(带参数)</button></>)
}

获取跳转参数

function Home() {const navigator = useNavigate()return (<><h1>Home</h1><Link to="/cate?title=大前端">跳转到分类页</Link><button onClick={() => navigator("/cate/100?title=Java")}>跳转到分类页(带参数)</button></>)
}function Cate() {// 获取路由动态参数的数据const params = useParams()// 获取查询参数?后面的数据const [searchParams] = useSearchParams()console.log(searchParams); // URLSearchParams {size: 1}return (<><h1>Cate</h1><div>{JSON.stringify(params)}</div>{/* {id: '100'} */}<div>{JSON.stringify(searchParams.get("title"))}</div>{/* Java */}</>);
}

路由模式

各个主流框架的常用路由模式有两种,分别是 historyhash 模式, ReactRouter 分别由 createBrowerRoutercreateHashRouter 函数负责创建

路由模式url表现底层原理
historyurl/loginhistory 对象 + pushState事件
hashurl/#/login监听 hashChange 事件

路由懒加载

默认情况下像以下代码在页面被访问时尽管条件为 false , 组件也一样会被加载。而如果使用了路由懒加载,那么只有条件满足时候 或者说 组件被使用时才会被加载,这样有助于性能优化及加载速度

{false && <Article>}

假设 pages 中有 HomeCate 组件,我们可以通过 lazy 将他们定义为懒加载模式

const router = createBrowserRouter([{path: "/",lazy: () => import("@/pages/Home/index.tsx")},{path: "/cate",// 可以省略:index.tsxlazy: () => import("@/pages/Cate")}
])

loader

通过 loader 函数我们可以在页面 渲染之前 传递给页面指定的数据,并通过 useLoaderData 来接收数据

function Cate() {const loaderData = useLoaderData()console.log(loaderData); // Hello Worldreturn ...
}const router = createBrowserRouter([{path: "/",element: <Layout />,children: [{index: true,element: <Home />},{page: "/cate/:id",element: <Cate />,loader: ({params}) => {return "Hello World!"}}]}
])

数据也可以是异步的,通常用于获取后端接口的数据

loader: () => {return new Promise((resolve) => {setTimeout(() => {resolve("Hello World!")}, 3000)})
}

还可以获取路由参数,通过参数来获取对应的数据

{path: "/cate/:id",element: <Cate />,loader: ({ params }) => {return new Promise((resolve) => {setTimeout(() => {resolve(`分类的参数:${params.id}`)}, 3000)})}
}

API

useLocation

该方法返回当前 location 对象,主要用于监听路由的变化执行对应的逻辑

function Home() {let location = useLocation();useEffect(() => {// 逻辑代码}, [location]);return ...;
}

假如访问:/cate/100?title=Java#123,那么 location 的结果如下

{"pathname":"/cate/100","search":"?title=Java","hash":"#123","state":{"data":"Hello World!"},"key":"8lu1q217"}

useNavigate

该方法主要用于编程式导航的跳转

function Home() {const navigator = useNavigate()return (<><div onClick={() => navigator("/cate")}>跳转</div></>)
}

replace

指定 replace: true 将替换历史记录堆栈中的当前条目,而不是添加新的条目。简单来说就是默认情况下它的值为 false 也就意味着当你从 A 页面跳转到 B 页面时,点击浏览器的回退功能可以正常回退到 A 页面。但如果将值设置为 true 则跳转到 B 页面时无法回退到 A 了,因为 A 的历史记录栈被 B 替换了

navigator("/cate", { replace: true })
<Navigate to="/cate" replace />

preventScrollReset

默认情况下该参数的值为 false,表示组件重新渲染或重新跳转进入时会自动滚到顶部,如果设置为 true 则表示保持当前位置

state

在跳转时也可以通过 state 进行传递数据,通过 useLocation 接收数据

navigator("/cate", { state: { data: "Hello World!" } })
<Navigate to="/cate" state={{ data: "Hello World!" }} />

示例:

function Home() {const navigator = useNavigate()return (<><h1>Home</h1><div onClick={() => navigator("/cate", { state: { data: "Hello World!" } })}>跳转</div></>)
}function Cate() {const location = useLocation()return (<><h1>Cate</h1><div>{JSON.stringify(location.state)}</div>{/* {"data":"Hello World!"} */}</>);
}

<Navigate> 该组件会在渲染时自动重定向到指定的路径。它是 useNavigate 的组件包装器,并接受与 props 相同的所有参数

我们可以应用于以下场景:当有 token 时显示页面,反之跳转到 login

import { Navigate } from 'react-router-dom'const AuthRoute = ({ children }: { children: React.ReactNode }) => {const token = "..."if (token) {return <>{children}</>} else {return <Navigate to="/login" replace />}
}export default AuthRoute

http://www.mrgr.cn/news/57705.html

相关文章:

  • 完整的模型训练套路 pytorch
  • 解锁PDF权限密码
  • 前端开发:Vue中数据绑定原理
  • C:浅谈数组指针的声明
  • 深入探索路由算法的核心原理与应用
  • 报表工具怎么选?山海鲸VS帆软,哪个更适合你?
  • ORA-12170: TNS: 连接超时,oracle透过防火墙windows设置USE_SHARED_SOCKET=TRUE
  • 牛客网热度最高的17套一线大厂Java面试八股文!面面俱到,太全了
  • 国家眼部疾病临床病例集《眼视光案例荟》首刊在三亚隆重发布
  • 070_基于springboot的Q高中素质评价档案系统
  • Three.js 使用着色器 实现跳动的心
  • 2D拓扑图
  • 项目模块七:TimerWheel模块
  • IEEE 802.3-2012 Clause 22.2.4.2
  • NacosException: Client not connected, current status:STARTING异常解决
  • 在线制作拼团活动步骤是什么
  • java线程池大小与CPU关系
  • Unity插件-Intense TPS 讲解
  • 【Kubernetes实战】Kubernetes集群搭建(虚拟机环境,一主两从)
  • Pandas 文件读取与保存指南:高效处理 CSV、Excel 等多种格式数据
  • 【算法设计与分析】-回溯法的回忆-学习【期末复习篇章】
  • 绘画相关,MIDI
  • js中for...in 和 for...of 区别
  • java生成可执行文件
  • Java中的反射是什么?如何使用反射API?
  • 回归模型的增量学习的经典文章和方法