【react框架】更新更麻了,React Router 6的使用学习记录

前言

代码来源B站尚硅谷教学视频,可结合之前的路由文章【react框架】学习记录9-学习路由react-router-dom的使用

React Router 以三个不同的包发布到 npm 上,它们分别为:

  1. react-router:路由的核心库,提供了很多的:组件、钩子。

  2. react-router-dom:包含react-router所有内容,并添加一些专门用于 DOM 的组件,例如 <BrowserRouter>等 。

  3. react-router-native:包括react-router所有内容,并添加一些专门用于ReactNative的API,例如:<NativeRouter>等。

                              --尚硅谷md文档
    

安装

yarn add react-router-dom

默认安装的是6版本


选择路由模式

history

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

ReactDOM.render(
	<BrowserRouter>
		<App/>
	</BrowserRouter>,
	document.getElementById('root')
)

hash

用法一样,只是把标签改为HashRouter


LInk/routes/route

这几个放在一起讲。routes代替了原先的switch,并且是必写的,不写react会报错。

import {NavLink,Routes,Route} from 'react-router-dom'

<Link className="item" to="/about">About</NavLink>
<Link className="item" to="/home">Home</NavLink>

<Routes>
	<Route path="/about" element={<About/>}/> // 注意哦,组件注册的写法变了
	<Route path="/home" element={<Home/>}/>
</Routes>

其中Route标签支持一个属性caseSensitive,为true的时候,路由的路径就开启严格匹配模式,默认是false,路径不区分大小写。

6版中不需要使用专门使用Route去匹配路由了


Navigate

代替了Redirect标签

import React,{useState} from 'react'
import {Navigate} from 'react-router-dom'

export default function Home() {
	const [sum,setSum] = useState(1)
	return (
		<div>
			<h3>我是Home的内容</h3>
			{/* 根据sum的值决定是否切换视图 */}
			{sum === 1 ? <h4>sum的值为{sum}</h4> : <Navigate to="/about" replace={true}/>}
			<button onClick={()=>setSum(2)}>点我将sum变为2</button>
		</div>
	)
}

其中有个replace属性,当为true的时候,push模式变成replace模式。

注意:当渲染Navigate标签的时候,如果Navigate标签不在routes的话,是真实的跳转到对应的组件页面,而不是像子组件一样渲染。


Navlink

舍弃了activeClassName属性,统一用className完成激活样式。可以写入一个函数,默认的入参是一个对象,里面有个标识是否激活的属性isActive:

<NavLink
    to="login"
    className={({ isActive }) => {
        console.log('home', isActive)
        return isActive ? 'base one' : 'base'
    }}
>login</NavLink>

如果有多个NavLink标签可以写成一个方法直接在className中执行达到复用的效果。

后面会提到嵌套路由,当子路由的NavLink标签高亮的时候,同时父路由的NavLink也是高亮的,如果业务需求不需要父路由的NavLink高亮,可以在父级的NavLink标签上加end属性取消子路由匹配后的高亮。

<NavLink to="home" end >home</NavLink>

useRoutes使用路由表

就是和vue-router的路由统一管理一样的。

可以在src/routes/index.js中创建路由表配置

import About from '../pages/About'
import Home from '../pages/Home'
import {Navigate} from 'react-router-dom'

export default [
	{
		path:'/about',
		element:<About/>
	},
	{
		path:'/home',
		element:<Home/>
	},
	{
		path:'/',
		element:<Navigate to="/about"/>
	}
]

然后在需要显示路由组件的组件中:

import React from 'react'
import {NavLink,useRoutes} from 'react-router-dom'
import routes from './routes'

export default function App() {
	//根据路由表生成对应的路由规则
	const element = useRoutes(routes)
	return (
		<div>
				......
	      {/* 注册路由 */}
	      {element}
			  ......
		</div>
	)
}

嵌套路由

首先在路由表中写入子路由配置

const element = useRoutes([
  {
    path:'/about',
    element:<About/>
  },
  {
    path:'/home',
    element:<Home/>,
    children:[
      {
        path:'news',
        element:<News/>
      },
      {
        path:'message',
        element:<Message/>,
      }
    ]
  }
])

然后利用Outlet标签做显示,原理和vue的router-view标签一样的:

import React from 'react'
import {NavLink,Outlet} from 'react-router-dom'

export default function Home() {
	return (
		<div>
			<h2>Home组件内容</h2>
			<div>
				<ul className="nav nav-tabs">
					<li>
						<NavLink className="list-group-item" to="news">News</NavLink>
					</li>
					<li>
						<NavLink className="list-group-item" to="message">Message</NavLink>
					</li>
				</ul>
				{/* 指定路由组件呈现的位置 */}
				<Outlet />
			</div>
		</div>
	)
}

注意二级路由的to属性不要加/符号了,否则又是跳转一级路由


hooks传参

在函数式组件中由于获取不到this,所以react提供了几个hooks用于路由的信息获取

useParams获取params参数

params参数的接收用useParams:

{/* 向路由组件传递params参数 */}
<Link to={`/home/message/detail/${ obj.id }/${ obj.title }`}>{ obj.title }</Link>

{/* 声明接收params参数 */}
<Route path="/home/message/detail/:id/:title" element={ Zizujian }/> // 或者在路由表中配置

// 子组件接收参数
import { Routes, Route, useParams } from 'react-router-dom';

let { id } = useParams(); // 获取传参

useSearchParams获取search参数

search参数的接收用useSearchParams:

// 父组件
<Link to={`/home/message/detail/?id=${ obj.id }&title=${ obj.title }`}></Link>

// 子组件
import React from 'react'
import {useSearchParams} from 'react-router-dom'

export default function Detail() {
	const [search,setSearch] = useSearchParams() // 和stateHook的用法一样
	const id = search.get('id') // 只是获取到的search是个封装好的类型,需要get获取数据
	const title = search.get('title')
	const content = search.get('content')
	return (
		<ul>
			<li>
				<button onClick={()=>setSearch('id=008&title=哈哈&content=嘻嘻')}>点我更新一下收到的search参数</button> // 更新search参数
			</li>
			<li>消息编号:{id}</li>
			<li>消息标题:{title}</li>
			<li>消息内容:{content}</li>
		</ul>
	)
}

useMatch获取match

获取路由匹配信息,之前router5的时候,我们获取params参数就是从这里拿取的:

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

const match = useMatch('/login/:x/:y') // 需要传入匹配的路由
console.log('params', match.params)

useLocation获取location

获取当前 location 信息,之前router5是通过location属性获取search参数:

import {useLocation} from 'react-router-dom'

const location = useLocation() // 不需要传入路由
console.log('search', location.search)

state的参数也是从这个api拿取的

// 父组件
<Link to='/home/message/detail', state:{ id: obj.id, title: obj.title }}}>{ obj.title }</Link>

// 子组件
import {useLocation} from 'react-router-dom'

const location = useLocation() // 不需要传入路由
console.log('state', location.state)

useNavigate实现编程式导航

import React from 'react'
import {useNavigate} from 'react-router-dom'

export default function Demo() {
  const navigate = useNavigate()
  const handle = () => {
    //第一种使用方式:指定具体的路径
    navigate('/login', 
      replace: false,
      state: {a:1, b:2},
      search: 'id=11' // 动态参数
    }) 
    //第二种使用方式:传入数值进行前进或后退,类似于5.x中的 history.go()方法
    navigate(-1)
  }
  
  return (
    <div>
      <button onClick={handle}>按钮</button>
    </div>
  )
}

useInRouterContext判断是否被路由标签包裹

就是用来判断组件是否在<BrowserRouter>标签的包括范围内,是返回 true,否则返回 false。

import {useInRouterContext} from 'react-router-dom'

console.log("@“, useInRouterContext())

useNavigationType获取路由跳转方式

import {useNavigationType} from 'react-router-dom'

console.log('useNavigationType', useNavigationType()) // PUSH REPLACE POP(原地刷新)

useOutlet获取当前组件中渲染的嵌套路由实例

const result = useOutlet()
console.log(result)
// 如果嵌套路由没有挂载,则result为null
// 如果嵌套路由已经挂载,则展示嵌套的路由对象

useResolvedPath解析rul

console.log(useResolvedPath('/home?id=1&name=22')) // 解析出对象的形式,有path、search、hash等

useRouteLoaderData路由表传hook

没想到吧,路由表还可以传参数,而且通过hook的方式传的。

先写个要传的hook:

import api from '@/api'

export default async function AuthLoader() {
  const data = await api.getPermissionList()
  return {
    data
  }
}

然后路由表配置好这个hook

// 引入
{
    id: 'layout',
    element: <Layout />,
    loader: AuthLoader,
    ...

在Layout组件中使用(好像在它的子组件里也是可以用的,在其他组件里没试过)

import { useRouteLoaderData } from 'react-router-dom'
// ...
const data = useRouteLoaderData('layout')

结合TS

给个写法参考吧,不保证时效性,在router/index.tsx文件(注意后缀!!):

import { createBrowserRouter } from 'react-router-dom'
import React from 'react' // 必须引入否则报错
import Home from '../pages/Home'
import NotFound from '../pages/NotFound'

const router = createBrowserRouter([
  {
    path: '/',
    element: <Home />,
  },
  {
    path: '*', // 404 路由配置,都写在最后(兜底)
    element: <NotFound />,
  },
])

export default router

在App.tsx:

import React from 'react'
import { RouterProvider } from 'react-router-dom'
import routerConfig from './router'

import './App.css'

function App() {
  return <RouterProvider router={routerConfig}></RouterProvider>
}

export default App
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值