前言
代码来源B站尚硅谷教学视频,可结合之前的路由文章【react框架】学习记录9-学习路由react-router-dom的使用
React Router 以三个不同的包发布到 npm 上,它们分别为:
-
react-router:路由的核心库,提供了很多的:组件、钩子。 -
react-router-dom:包含react-router所有内容,并添加一些专门用于 DOM 的组件,例如 <BrowserRouter> 等 。 -
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,路径不区分大小写。
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 === 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:
{}
<Link to={`/home/message/detail/${ obj.id }/${ obj.title }`}>{ obj.title }</Link>
{}
<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()
const id = search.get('id')
const title = search.get('title')
const content = search.get('content')
return (
<ul>
<li>
<button onClick={()=>setSearch('id=008&title=哈哈&content=嘻嘻')}>点我更新一下收到的search参数</button>
</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}
})
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())
useOutlet获取当前组件中渲染的嵌套路由实例
const result = useOutlet()
console.log(result)
useResolvedPath解析rul
console.log(useResolvedPath('/home?id=1&name=22'))
|