概念介绍
React是一个库。包含的核心内容:JSX+组件
React官方并没有提供我们需要的路由模块。推荐使用第三方的路由模块React-Router(组件)。
ReactRouter也是组件,我们下载这个插件,引入对应的路由组件。搭建我们的路由
- Vue的路由称为配置式路由。将所有路由信息放在js文件中。提供一个渲染出口就可以
- ReactRouter提供的路由编程式路由,我们需要在哪个地方使用路由,代码就写在那个组件中
- 约定式路由,按照约定的目录来设计组件或者页面,自动生成路由。umijs
基础使用
安装
yarn add react-router-dom@6
介绍
路由模式
分为BrowserRouter和HashRouter两种模式
使用时都是包裹整个应用,一个 React 应用只需要使用一次
- BrowserRouter
- 使用 H5 的
history.pushStateAPI 实现(http://localhost:3000/first)
- 使用 H5 的
HashRouter
- 使用 URL 的哈希值实现(http://localhost:3000/#/first)
Link
- 使用 URL 的哈希值实现(http://localhost:3000/#/first)
用于指定导航链接,完成路由跳转
-
Routes
提供一个路由出口,满足条件的路由组件会渲染到组件内部,定义path和组件的对应关系
Route
用于指定导航链接,完成路由匹配
path属性指定匹配的路径地址,element属性指定要渲染的组件配置路由
```javascript import React from ‘react’ import { BrowserRouter, HashRouter, Routes, Route, Navigate } from ‘react-router-dom’
import Login from ‘./Login’;
import Reg from ‘./Reg’;
import Home from ‘./Home’;
import NotFound from ‘./NotFound’;
import Person from ‘./Person’;
import Goods from ‘./Goods’;
export default function RouterContainer () {
return (
<a name="ZB00G"></a>### 配置嵌套路由1. 在需要嵌套二级路由的`Route`下嵌套`Route`路由,注意`path`前面不要加`/`2. 在需要嵌套二级路由组件里引入`Outlet`钩子3. 配置路由出口`<Outlet />`4. 访问`/一级路由/二级路由` `http://localhost:5173/home/person````javascriptimport React from 'react'import { BrowserRouter, HashRouter, Routes, Route, Navigate } from 'react-router-dom'import Login from './Login';import Reg from './Reg';import Home from './Home';import NotFound from './NotFound';import Person from './Person';import Goods from './Goods';export default function RouterContainer () {return (<BrowserRouter><Routes>// /Navigate组件在这里用作重定向<Route path="/" element={<Navigate to="/home" replace />} /><Route path="/login/:id" element={<Login />} /><Route path="/login" element={<Login />} /><Route path="/reg" element={<Reg />} /><Route path="/home" element={<Home />}><Route path="person" element={<Person />} /><Route path="goods" element={<Goods />} /></Route>// 当浏览器地址栏输入的url没有匹配到配置的路由时,渲染NotFound组件<Route path="*" element={<NotFound />} /></Routes></BrowserRouter>)}
import React from 'react'import { Outlet } from 'react-router-dom'import './home.scss'export default function Home () {return (<div className='home'><div className='left'><div>人员管理</div><div>商品管理</div></div><div className='right'>{/**路由出口 */}<Outlet /></div></div>)}
Index Route
如果跳转到/home的时候还想做一个重定向,或者渲染一个默认内容,则可以使用Index Route
import React from 'react'import { BrowserRouter, HashRouter, Routes, Route, Navigate } from 'react-router-dom'import Login from './Login';import Reg from './Reg';import Home from './Home';import NotFound from './NotFound';import Person from './Person';import Goods from './Goods';export default function RouterContainer () {return (<BrowserRouter><Routes>// /Navigate组件在这里用作重定向<Route path="/" element={<Navigate to="/home" replace />} /><Route path="/login/:id" element={<Login />} /><Route path="/login" element={<Login />} /><Route path="/reg" element={<Reg />} /><Route path="/home" element={<Home />}><Route indexelement={<div>`/home`路径的默认内容,也可以单独封装一个组件</div>} /><Route path="person" element={<Person />} /><Route path="goods" element={<Goods />} /></Route>// //当浏览器地址栏输入的url没有匹配到配置的路由时,渲染NotFound组件<Route path="*" element={<NotFound />} /></Routes></BrowserRouter>)}
当父路由被匹配,但是子路由没有被匹配的时候,Index Route会被匹配,即:Index Route对应的element会被渲染出来
路由跳转
通过Link或者NavLink组件跳转
如果在跳转时不想加历史记录,可以添加额外参数replace为true
import {Link,NavLink} from 'react-router-dom'<Link to="/login" replace>Link跳转到登录</Link><NavLink to="/login" replace>NavLink跳转到登录</NavLink>
通过js跳转
import React from 'react';import {useNavigate} from 'react-router-dom';export default function AddAccount() {const navigate = useNavigate();function goToLogin(){navigate("/login");}return (<div>Goods <button onClick={goToLogin}>跳转到登录</button></div>)}
路由传参
url parmas
- 在
Route组件匹配的path中加上动态路由path='/xxx/:id' - 在
navigate跳转路由后加上参数navigate('/xxx/参数') - 在跳转组件中引入
useParams钩子 - 调用
useParams赋值给 params params对象中可以获取到对应参数
假设/reg路径需要接受一个参数,则在路由配置登录路径的时候,要做如下处理
<BrowserRouter><Routes><Route path="/" element={<Navigate to="home" replace />} />{/* 动态路由接收参数 */}<Route path="/login/:id" element={<Login />}></Route></Routes></BrowserRouter>
跳转的时候传递参数
import { useNavigate } from 'react-router-dom'function Home () {// 只能够在函数组件的根部调用,不可以放在条件语句或者某个自定义函数内部去调用const navigate = useNavigate()const toLogin = () => {// 直接在path后面加参数navigate('/login/1001')}return (<div>Home<button onClick={toLogin}>去Login</button></div>)}export default Home
获取路由参数
// 引入 useParams 钩子import { useParams } from 'react-router-dom'function Login () {// 调用 useParams 赋值给 paramsconst params = useParams()return (<div>{/* 使用传来的参数 */}params参数{params.id}</div>)}export default Login
import React, { Component } from 'react'export default class Login extends Component {render(){// 接收params参数console.log(this.props.match.params)}}
searchParams
- 引入
useSearchParams钩子 - 调用
useSearchParams函数,通过结构赋值拿到params对象 - 调用
params对象的get方法,将要获取的路由参数作为实参传入 ```javascript import { useNavigate } from ‘react-router-dom’ function Login () { const navigate = useNavigate() const toAbout = () => { navigate(‘/about?id=1001&name=loveZero’) } return (Login) }
export default Login
接收参数```javascript// 引入 useSearchParams 钩子import { useSearchParams } from 'react-router-dom'function About () {// 调用 useSearchParams 函数,通过结构赋值拿到 params 对象const [params] = useSearchParams()// 调用 params 对象的 get 方法,将要获取的路由参数作为实参传入let id = params.get('id')let name = params.get('name')return (<div>About---{id}---{name}</div>)}export default About
import React, { Component } from 'react'//获取到的search是urlencoded编码字符串,需要借助querystring解析import qs from 'querystring'let obj = { id: 1, name: 'mingming' }console.log(qs.stringify(obj)) // id=1&name=mingming 这是urlencoded格式let query = 'id=1&name=mingming'console.log(qs.parse(query)) // {id: "1", name: "mingming"}export default class About extends Component {render(){// 接收search参数console.log(this.props.location.search)}}
路由懒加载
通过react自带的方法 React.lazy和React.Suspense实现(推荐的方式)
以登录、注册和首页为例
- 所有需要懒加载的组件都要使用React.lazy处理一次,返回一个新的组件
React.Suspense可以指定加载指示器(loading indicator),懒加载的组件必须位于React.Suspense下方import React from 'react';import { BrowserRouter, Routes, Route } from 'react-router-dom';const Login = React.lazy(() => import("./pages/Login"));const Reg = React.lazy(() => import("./pages/Reg"));const Home = React.lazy(() => import("./pages/Home"));const NotFound = React.lazy(() => import("./pages/NotFound"));function App () {return (<React.Suspense fallback={<div>加载中...</div>}><BrowserRouter><Routes><Route path="/" element={<Navigate to="home" replace />} /><Route path="/login" element={<Login />}></Route><Route path="reg" element={<Reg />} /><Route path="home" element={<Home />} /><Route path="*" element={<NotFound />} /></Routes></BrowserRouter></React.Suspense>);}export default App;
配置式路由
ReactRouter默认提供的是路由编程式路由,也可以采用配置式路由的方式useRoutesuseRoutes只能在BrowserRouter或者HashRouter的子组件中使用 ```javascript import React from ‘react’ import { BrowserRouter } from ‘react-router-dom’
import MyRouters from ‘./MyRouter.jsx’
export default function RouterContainer () {
return (
```javascriptimport React from 'react'import { Navigate, useRoutes } from "react-router-dom"import Login from './Login';import Reg from './Reg';import Home from './Home';import NotFound from './NotFound';import Person from './Person';import Goods from './Goods';const routes = [{path: '/',element: <Navigate to="/home" />},{path: "/login/:code",element: <Login />},{path: "/login",element: <Login />},{path: "/reg",element: <Reg />},{path: "/home",element: <Home />,children: [{index: true,element: <div>`/home`路径的默认内容,也可以单独封装一个组件</div>,},{path: "person",element: <Person />,},{path: "goods",element: <Goods />}]},{path: "*",element: <NotFound />}]export default function MyRouters () {const element = useRoutes(routes)return element}
