目录
1.一级路由
2.?重定向
3.Routes 和 Route
?4.NavLink 自定义激活样式名
?5.useRoutes 路由表
?6.多级路由 嵌套路由
????????6.1 路由表内书写嵌套路由
????????6.2 嵌套路由的使用
????????6.3 仅当前标签高亮显示?
7.路由的三种传参
????????7.1 params传参
????????7.2 search 传参
????????7.3 state 传参
8.编程式路由
9.useInRouterContext()
10.useNavigationType()
11.useOutlet()
12.useResolvePath()
在5的基础上学习6
常用的npm包是 react-router-dom 默认按照6版本
现在react 推荐使用函数式组件
1.一级路由
不使用Switch,引入新的组件 Routes
// 1.解构赋值引入需要使用的路由组件
import { Route, Routes } from "react-router-dom"
router 6里面的更改如下:
1、Switch 没了,替换的是Routes。且必须写Routes,不像Switch一样可以不写。同时Routes也保证了匹配效率,匹配后就不往后匹配了
2、Route 内不使用 components 而是使用 element 且内部写组件标签
{/* <Switch>
? ? ? <Route path="/about" component={About} /> */}
<Routes>
? ? ? <Route path="/about" element={<About />} />
? ? ? <Route path="/home" element={<Home />} />
</Routes>
2.?重定向
首次使用router6,会出现下面的问题。这个表示路径“ / ” 没有对应组件
?5内引入 Redirect 解决。6 内引入 Navigate 组件
// 1.解构赋值引入需要使用的路由组件
import { Route, Routes ,Navigate} from "react-router-dom"
<Routes>
? ? ? ? ? ? ? ? ? <Route path="/about" element={<About />} />
? ? ? ? ? ? ? ? ? <Route path="/home" element={<Home />} />
? ? ? ? ? ? ? ? ? <Route path="/" element={<Navigate to="/about" />} />
? ? ? ? ? ? ?</Routes>
?Navigate 默认push 可以设置replace属性为true切换跳转模式
3.Routes 和 Route
Route相当if语句,对路径进行判断。Routes 必须和 Route 配合使用。
可以使用 caseSensitive 指定是否区分大小写,默认为 false 不区分
<Routes>
? ? ? ? ? ? ? ? ? <Route path="/about" element={<About />} />
? ? ? ? ? ? ? ? ? <Route path="/home" element={<Home />} />
? ? ? ? ? ? ? ? ? <Route path="/" element={<Navigate to="/about" />} />
? ? ? ? ? ? ?</Routes>
?4.NavLink 自定义激活样式名
router 6 内,不再使用activeClassName,取而代之的是className中写入函数,用函数来判断当前路由是否激活
由于每个NavLink都可能要自定义激活的样式名称,代码会有重复,那么可以在render外定义函数,进行复用。
? function getClassName = ({isActive})=>{
? ? return isActive? "list-group-item active_nav" : "list-group-item"
? }
render() {
? ? return (
? ? ? /* <NavLink activeClassName='active_nav' className="list-group-item" {...this.props}/>
? ? ? ? 6 内,不再使用activeClassName,取而代之的是className中写入函数,用函数来判断当前路由是否激活。
? ? ? */
? ? ? <NavLink className={getClassName} {...this.props}/>
? ? )
? }
?5.useRoutes 路由表
这是我们定义的路由规则,可以发现每一行其实仅路径和组件不一样,其余均一样,有较多重复。
<Routes>
? ? ? ? ? ? ? ? ? <Route path="/about" element={<About />} />
? ? ? ? ? ? ? ? ? <Route path="/home" element={<Home />} />
? ? ? ? ? ? ? ? ? <Route path="/" element={<Navigate to="/about" />} />
? ? ? ? ? ? ?</Routes>
router 6 提供了useRoutes方法,可以根据提供的路由表来自动生成下面的路由规则
路由表定义在routes内
?和组件,路由同级。
routes/index.js
//引入 route 需要用的组件
import { Navigate } from "react-router-dom";
// 引入对应路由组件
import About from "../pages/About";
import Home from "../pages/Home";
// 默认暴露出去
export default [
? ? {
? ? ? ? path:'/about',
? ? ? ? element:<About/>
? ? },
? ? {
? ? ? ? path:'/home',
? ? ? ? element:<Home/>
? ? },
? ? {
? ? ? ? path:'/',
? ? ? ? element:<Navigate to="/about"/>
? ? },
]
这里的路由表和vue内的路由基本一样。且将全部路由放在一个文件内,可以更加方便的去进行管理和修改。
在App.js 组件内的使用
// 1.解构赋值引入需要使用的路由组件
import {useRoutes } from "react-router-dom"
// 2.引入 路由表
import routes from './routes'
? // 根据路由表生成对应路由规则
? const element = useRoutes(routes)
?在原先注册路由的位置,写{element} 即可
? ? ? ? {/* 注册路由 */}
? ? ? ? ? {element}
?6.多级路由 嵌套路由
????????6.1 路由表内书写嵌套路由
????????可以给上一级路由书写children属性,来书写子级路由
????????routes/index.js
?{
? ? ? ? path:'/home',
? ? ? ? element:<Home/>,
? ? ? ? /* 多级路由,使用children */
? ? ? ? children:[
? ? ? ? ? ? {
? ? ? ? ? ? ? ? // 路径只用写子级路径即可,斜杠 / 不用写
? ? ? ? ? ? ? ? path:'news',
? ? ? ? ? ? ? ? element:<News/>
? ? ? ? ? ? },
? ? ? ? ? ? {
? ? ? ? ? ? ? ? path:'message',
? ? ? ? ? ? ? ? element:<Message/>
? ? ? ? ? ? }
? ? ? ? ]
? ? },
????????6.2 嵌套路由的使用
????????首先是路由链接,和往常一样使用NavLink 或者自定义 MyNavList都可以。
????????其中路由路径的写法有三种:
????????①/home/news ?②./news ③news
<ul className="nav nav-tabs">
? ? ? ? ? ? {/* 路由链接 多级路由的路径有三种写法
1、全写/home/news ?2、加前缀 ./news ? 3、 简写 ?news*/}
? ? ? ? ? ? <li>
? ? ? ? ? ? ? <MyNavList to="/home/news">News</MyNavList>
? ? ? ? ? ? </li>
? ? ? ? ? ? <li>
? ? ? ? ? ? ? <MyNavList to="/home/message">Message</MyNavList>
? ? ? ? ? ? </li>
? ? ? ? ? </ul>
?????????接着是路由展示。因为路由注册已经全部写在路由表内,只需要在最外层使用一次即可。需要用到 Outlet 组件
import { Outlet } from 'react-router-dom';
...
? ? ? ? ?
<ul>
...
</ul>
{/* 注册路由 与原先不同,这里要使用 Outlet 组件 来指定多级路由展示的位置*/}
<Outlet />
????????6.3 仅当前标签高亮显示?
????????项目有可能要求仅当前点击的标签高亮,原先标签或者前一级包裹的标签不显示高亮。这时候可以在上一级标签内使用end属性。
?接要求只用 News 高亮,而Home不高亮。给标签添加end属性即可?
? <MyNavList to="/about">About</MyNavList>
? ? ?{/* 如果只想当前点击的组件的标签高亮,若不是所以关联的都高亮,可以添加end 属性
那么就只高亮当前的标签。 */}
? <MyNavList to="/home" end >Home</MyNavList>
?
?
7.路由的三种传参
参数的传递包括三步:
①怎么传递 ②怎么声明 ③怎么获取
以图为例,传递是在Message组件内,声明在路由表内,接收在Detail组件内
????????7.1 params传参
????????传递:有路由链接的组件内
? {/* params 参数 路径上携带,同时路由表内要占位*/}
<Link to={`detail/${m.id}/${m.title}/${m.context}`} >{m.title}</Link>
????????声明:路由表内
{
? ? path:'message',
? ? element:<Message/> ,
? ? children:[
? ? ? ?{
? ? ? ? /* params 参数要占位 */
? ? ? ? path:'detail/:id/:title/:context',
? ? ? ? element:<Detail/>
? ? ? ?}
? ? ]
}
????????接收:跳转的路由组件内
????????可以使用 useParams 或useMatch ,推荐前者。
? // params参数
? // 使用useParams可以接收params参数
? const {id,title,context} = useParams()
? // useMatch 也可以获取参数,但是要输入完整路径,不然获取不到。比较麻烦,还是上面的常用
const m = useMatch('/home/message/detail/:id/:title/:context')
? console.log(m);
????????7.2 search 传参
????????传递:有路由链接的组件内
? ? ?{/* search 参数 传参是kv对 ?开头,多个参数 & 连接 */}
? ? ?<Link
to={`detail?id=${m.id}&title=${m.title}&context=${m.context}`} >
{m.title}
</Link>
?声明:路由表内
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? /* search 参数不用占位 */
? ? ? ? ? ? ? ? ? ? ? ? path:'detail',
? ? ? ? ? ? ? ? ? ? ? ? element:<Detail/>
? ? ? ? ? ? ? ? ? ? }
?????????接收:跳转的路由组件内
// search 参数
? // 使用useSearchParams 可以接受search 参数,但是要使用解构赋值,才可以获取到对应的数据
? const [search,setSearch] = useSearchParams()
? // 再使用对应的get方法才可以获取对应的数据
? const id = search.get('id')
? const title = search.get('title')
? const context = search.get('context')
? // 第二个结构赋值的是 更新search参数的方法,了解即可。和setState 类似
????????7.3 state 传参
????????传递:有路由链接的组件内
{/* state参数 ,传的是对象 */}
? ? ? ? ? ? ? ? <Link
? ? ? ? ? ? ? ? to="detail"
? ? ? ? ? ? ? ? state={
? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? id:m.id,
? ? ? ? ? ? ? ? ? ? title:m.title,
? ? ? ? ? ? ? ? ? ? context:m.context
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } >{m.title}</Link>
?声明:路由表内
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? /* state参数不用占位 */
? ? ? ? ? ? ? ? ? ? ? ? path:'detail',
? ? ? ? ? ? ? ? ? ? ? ? element:<Detail/>
? ? ? ? ? ? ? ? ? ? }
?接收:跳转的路由组件内
? // state 参数
? // 使用useLocation 接受,同时也可以接受 search参数,但是不好解析。所以 useLocation 就和 state 一起搭配使用
? // 直接解构赋值对应属性即可
? const {state:{id,title,context} }= useLocation()
8.编程式路由
在编码过程中,不一定是点击a标签进行跳转,可能是点击按钮,可以是鼠标滑到某个指定位置。那么在此时,一般的路由链接 Link,NavLink 就无法满足需求了。因此可以使用编程式路由跳转,在指定动作执行后,进行路由的跳转,跳转到指定的页面。
router6 是利用?useNavigate 生成 navigate 从而实现编程式路由
// 引入 useNavigate
import { useNavigate } from "react-router-dom";
// 在函数式组件内生成 navigate
export default function Message() {
// 编程式路由导航,就是使用useNavigate
const navigate = useNavigate()
// 按钮的回调函数
function showDetail(m){
// navigate 可以传两个参数,参数1是路径,参数2是对象
// 参数2,对象只能传递state参数。对象内还可以写replace,修改跳转模式
navigate("detail",{
state:{
id:m.id,
title:m.title,
context:m.context
}
})
// navigate 还可以传入数字,表示前进后退。
navigate(1)
}
return(
...
<button onClick={()=>{showDetail(m)}}>showDetail</button>
...
)
}
9.useInRouterContext()
判断当前组件是否在路由的上下文中,即组件的外侧是否有BrowerRouter包裹着。
一般是第三方组件,原来判断的。
10.useNavigationType()
返回当前的路由导航类型,即以何种路由跳转模式来到当前组件。
有三个值:POP , PUSH , REPLACE
其中 POP 表示 浏览器直接打开当前组件页面。刷新页面
11.useOutlet()
直接用console 输出 useOutlet()
如果该组件没有渲染到页面就是 null
渲染了就将该组件的一系列信息展示出来。
?
12.useResolvePath()
传入路径参数,用于解析路径
?
|