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

第三十二章 React路由组件的简单使用

1、NavLink的使用

一个特殊版本的 Link,当它与当前 URL 匹配时,为其渲染元素添加样式属性

<NavLink className="list-group-item" to="/home">Home</NavLink>
<NavLink className="list-group-item" to="/about">About</NavLink>

以上代码有一个默认的特殊效果,就是当你选中该路由时会有一个默认的激活样式,默认的类名:active

如果你要修改该激活样式,可以自定义样式:

.active1{background-color: orange !important;color: white !important;
}

添加一个属性activeClassName将类名active1填进去:

<NavLink className="list-group-item" activeClassName="active1" to="/home">Home</NavLink> <NavLink className="list-group-item" activeClassName="active1" to="/about">About</NavLink>

在这里插入图片描述

由于这里代码有些冗长,我们简单封装一下:

封装组件MyNavLink

import React, { Component } from 'react'
import { NavLink } from 'react-router-dom'
export default class MyNavLink extends Component {render() {return (<NavLink className="list-group-item" activeClassName="active1" {...this.props}/>)}
}

导入组件MyNavLink

import MyNavLink from './components/MyNavLink'

使用组件MyNavLink

<MyNavLink to="/home"  children="Home"/> 
<MyNavLink to="/about" children="About"/>

将标签属性tochildren传入组件,其中to属性的内容就是路由路径,children就是标签体内容。

小总结

  • NavLink可以实现路由链接的高亮,通过activeClassName指定样式类名
  • 标签体内容是一个特殊的标签属性
  • 通过this.props.children可以获取标签体内容

2、Switch的使用

渲染与该地址匹配的第一个子节点<Route>或者<Redirect>

import { Switch, Route } from 'react-router'<Switch><Route exact path="/" component={Home}/><Route path="/about" component={About}/><Route path="/:user" component={User}/><Route component={NoMatch}/>
</Switch>
  • 通常情况下pathcomponent是一一对应的关系

  • Switch可以提高路由匹配的效率(单一匹配)


解决多级路径刷新样式丢失的问题

  • public/index.html 中 引入样式时不写.// (常用)
  • public/index.html 中 引入样式时不写 ./ %PUBLIC_URL% (常用)
  • 使用HashRouter

路由的严格匹配与模糊匹配

  • 默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
  • 开启严格匹配:<Route exact={true} path="/about" component={About}/>
  • 严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由

3、Redirect组件的使用

页面重定向:一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由

<Switch><Route path="/about" component={About}/><Route path="/home" component={Home}/><Redirect to="/about"/>
</Switch>

详情参见:React路由之Redirect


4、路由嵌套

News组件:

import React, { Component } from 'react'export default class News extends Component {render() {return (<ul><li>news001</li><li>news002</li><li>news003</li></ul>)}
}

Message组件:

import React, { Component } from 'react'export default class Message extends Component {render() {return (<div><ul><li><a href="/message1">message001</a>&nbsp;&nbsp;</li><li><a href="/message2">message002</a>&nbsp;&nbsp;</li><li><a href="/message/3">message003</a>&nbsp;&nbsp;</li></ul></div>)}
}

Home组件:

import React, { Component } from 'react'
import { Switch, Route, Redirect } from 'react-router-dom'
import MyNavLink from '../MyNavLink'
import News from './News'
import Message from './Message'export default class Home extends Component {render() {// console.log('这是Home组件的Props',this.props)return (<div><h3>我是Home的内容</h3><div><ul className="nav nav-tabs"><li>{/* 注册子路由时要写上父路由的path值 */}<MyNavLink to="/home/news">News</MyNavLink></li><li><MyNavLink to="/home/message">Message</MyNavLink></li></ul>{/* 注册路由 */}<Switch>{/* 注册子路由时要写上父路由的path值 */}<Route path="/home/news" component={News} /><Route path="/home/message" component={Message} /><Redirect to="/home/news" /></Switch></div></div>)}
}

整体效果:

在这里插入图片描述


注意点:

1.注册子路由时要写上父路由的path

2.路由的匹配是按照注册路由的顺序进行的


5、向路由组件传递params参数

组件目录结构

src
|--components
|        |--Home
|             |--News
|             |--Message
|             		|--Detail
|        |--About
|        |--Header
|--App.jsx
|--index.js

主要组件Message

import React, { Component } from 'react'
import {Link,Route} from 'react-router-dom'
import Detail from './Detail'export default class Message extends Component {state = {msgArr: [{ id: '01', title: 'msg-01' },{ id: '02', title: 'msg-02' },{ id: '03', title: 'msg-03' },],}render() {const { msgArr } = this.statereturn (<div><ul>{msgArr.map((msgObj) => {return (<li key={msgObj.id}><Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>&nbsp;&nbsp;</li>)})}</ul><hr /><Route path="/home/message/detail/:id/:title" component={Detail}/></div>)}
}

URL匹配路径/home/message/:id/:title时渲染的组件。:id是一个参数,可以通过props.match.params.id访问。:title也是一样。

主要组件Detail

import React, { Component } from 'react'export default class Detail extends Component {state = {info:[{id:'01',content:'你好我是信息1'},{id:'02',content:'你好我是信息2'},{id:'03',content:'你好我是信息3'},]}render() {console.log(this.props)const {info} = this.stateconst {id,title} = this.props.match.paramsconst res = info.find(infoObj=>{return infoObj.id === id})return (<ul><li>ID:{id}</li> <li>TITLE:{title}</li> <li>CONTENT:{res.content}</li> </ul>)}
}

在这里我们通过解构this.props.match.params获得参数idtitle。以下是我们打印的标签属性:

history: Object { length: 44, action: "PUSH", location: {},}location: Object { pathname: "/home/message/detail/01/msg-01", search: "", key: "5ugqcd",}match: isExact: trueparams: Object { id: "01", title: "msg-01" }id: "01"title: "msg-01"path: "/home/message/:id/:title"url: "/home/message/01/msg-01"

从以上打印结果中,我们可以清晰的看到我们的参数位置:match.params

整体效果

在这里插入图片描述


小总结

  • 路由链接(携带参数):<link to='/demo/test/tom/19'>详情</Link>
  • 注册路由(声明接收):<Route path='/demo/test/:name/:age' component={Test} />
  • 接收参数:const {name,age} = this.props.match.params

6、向路由组件传递search参数

修改Message组件

import React, { Component } from 'react'
import {Link,Route} from 'react-router-dom'
import Detail from './Detail'export default class Message extends Component {state = {msgArr: [{ id: '01', title: 'msg-01' },{ id: '02', title: 'msg-02' },{ id: '03', title: 'msg-03' },],}render() {const { msgArr } = this.statereturn (<div><ul>{msgArr.map((msgObj) => {return (<li key={msgObj.id}>{/* 传递params参数 */}{/* <Link to={`/home/message/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>&nbsp;&nbsp; */}{/* 传递search参数 */}<Link to={`/home/message/detail?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>&nbsp;&nbsp;</li>)})}</ul><hr /><Route path="/home/message/detail" component={Detail}/></div>)}
}

这里的路由链接的参数需要使用?key=value&key=value的格式,也叫urlencode格式。路由注册照常即可,不需要声明参数。

修改Detail组件

import React, { Component } from 'react'
import qs from 'qs'
export default class Detail extends Component {state = {info:[{id:'01',content:'你好我是信息1'},{id:'02',content:'你好我是信息2'},{id:'03',content:'你好我是信息3'},]}render() {console.log(this.props)const {info} = this.stateconst {search} = this.props.locationconst {id,title} = qs.parse(search.slice(1))const res = info.find(infoObj=>{return infoObj.id === id})return (<ul><li>ID:{id}</li> <li>TITLE:{title}</li> <li>CONTENT:{res.content}</li> </ul>)}
}

这里引入了一个库qs,无需安装,直接引入即可,它有两个方法可以使得urlencode格式的数据与object格式的数据进行转换。

  • qs.stringify(): 将{a:'1',b:2}转换>a=1&b=2
  • qs.parse(): 将a=1&b=2转换>{a:"1",b:"2"}

查看标签属性:

history: Object { length: 7, action: "PUSH", location: {},}
location: hash: ""key: "0wurd0"pathname: "/home/message/detail"search: "?id=01&title=msg-01"state: undefinedmatch: Object { path: "/home/message/detail", url: "/home/message/detail/", isExact: true,}

我们可以看到search参数是一个字符串在location对象里面,所以我们只需要将它解构取出值,即可进行后续操作。


小总结

  • 路由链接(携带参数):<link to='/demo/test?name=tom&age=19'>详情</Link>
  • 注册路由(无需声明,正常注册即可):<Route path='/demo/test' component={Test} />
  • 接收参数:const {search} = this.props.location
  • 解析参数:获取到的searchurlencode编码字符串,需要借助qs解析。

7、向路由组件传递state参数

修改Message组件

import React, { Component } from 'react'
import {Link,Route} from 'react-router-dom'
import Detail from './Detail'export default class Message extends Component {state = {msgArr: [{ id: '01', title: 'msg-01' },{ id: '02', title: 'msg-02' },{ id: '03', title: 'msg-03' },],}render() {const { msgArr } = this.statereturn (<div><ul>{msgArr.map((msgObj) => {return (<li key={msgObj.id}>{/* 传递params参数 */}{/* <Link to={`/home/message/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>&nbsp;&nbsp; */}{/* 传递search参数 */}{/* <Link to={`/home/message/detail?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>&nbsp;&nbsp; */}{/* 传递state参数 */}<Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link>&nbsp;&nbsp;</li>)})}</ul><hr /><Route path="/home/message/detail" component={Detail}/></div>)}
}

对象的形式state参数放在路由链接里面。

修改的Detail组件

import React, { Component } from 'react'
// import qs from 'qs'
export default class Detail extends Component {state = {info:[{id:'01',content:'你好我是信息1'},{id:'02',content:'你好我是信息2'},{id:'03',content:'你好我是信息3'},]}render() {console.log(this.props)const {info} = this.stateconst {id,title} = this.props.location.state || {}// const {id,title} = qs.parse(search.slice(1))const res = info.find(infoObj=>{return infoObj.id === id}) || {}return (<ul><li>ID:{id}</li> <li>TITLE:{title}</li> <li>CONTENT:{res.content}</li> </ul>)}
}

获取state参数也是在location里面获取,我们可以看看标签属性的结构:

history: Object { length: 11, action: "REPLACE", location: {},}
location: hash: ""key: "o47hxa"pathname: "/home/message/detail"search: ""state: Object { id: "01", title: "msg-01" }match: Object { path: "/home/message/detail", url: "/home/message/detail", isExact: true,}

我们可以从打印结果里面清晰的看到state的参数


小总结

  • 路由链接(携带参数):<link to={{pathname:'/demo/test',state:{name:'tom',age:19}}}>详情</Link>
  • 注册路由(无需声明,正常注册即可):<Route path='/demo/test' component={Test} />
  • 接收参数:const {state} = this.props.location
  • 解析参数:刷新也可以保留住参数。

8、编程式路由导航

传递params参数

  1. 注册事件
<button onClick={() => this.pushRoute(msgObj.id, msgObj.title)}>push路由</button>
<button onClick={() => this.replaceRoute(msgObj.id, msgObj.title)}>replace路由</button>
  1. 事件逻辑
  pushRoute = (id, title) => {// push路由跳转===>params参数this.props.history.push(`/home/message/detail/${id}/${title}`)}replaceRoute = (id, title) => {// replace路由跳转===>params参数this.props.history.replace(`/home/message/detail/${id}/${title}`)}
  1. 注册路由
<Route path="/home/message/detail/:id/:title" component={Detail} />
  1. 接收参数
 const {id,title} = this.props.match.params

传递search参数

  1. 注册事件
<button onClick={() => this.pushRoute(msgObj.id, msgObj.title)}>push路由</button>
<button onClick={() => this.replaceRoute(msgObj.id, msgObj.title)}>replace路由</button>
  1. 事件逻辑
  pushRoute = (id, title) => {// push路由跳转===>search参数this.props.history.push(`/home/message/detail?id=${id}&title=${title}`)}replaceRoute = (id, title) => {// replace路由跳转===>search参数this.props.history.replace(`/home/message/detail?id=${id}&title=${title}`)}
  1. 注册路由
<Route path="/home/message/detail" component={Detail} />
  1. 接收参数
const {search} = this.props.location
const {id,title} = qs.parse(search.slice(1))

传递state参数

  1. 注册事件
<button onClick={() => this.pushRoute(msgObj.id, msgObj.title)}>push路由</button>
<button onClick={() => this.replaceRoute(msgObj.id, msgObj.title)}>replace路由</button>
  1. 事件逻辑
  pushRoute = (id, title) => {// push路由跳转===>state参数this.props.history.push('/home/message/detail', { id, title })}replaceRoute = (id, title) => {// replace路由跳转this.props.history.replace('/home/message/detail', { id, title })}
  1. 注册路由
<Route path="/home/message/detail" component={Detail} />
  1. 接收参数
const {id,title} = this.props.location.state || {}

小总结

编程式路由导航就是借助this.props.history身上的几个API进行路由的前进、后退、跳转、替换。

  • this.props.history.go()
  • this.props.history.goBack()
  • this.props.history.goForward()
  • this.props.history.push()
  • this.props.history.replace()

9、withRouter的使用

我们知道一般组件,如果不传标签属性,接收的props是一个空对象,是没有那些路由属性和API的,那么一般组件里面如何使用路由进行跳转呢?那就要使用withRouter对一般组件进行改造了。

import React, { Component } from 'react'
import {withRouter} from 'react-router-dom'class Header extends Component {back = () => {this.props.history.goBack()}forward = () => {this.props.history.goForward()}go1 = () => {this.props.history.go(-2)}render() {console.log('这是Header组件的Props',this.props)return (<div className="col-xs-offset-2 col-xs-8"><div className="page-header"><h2>React Router Demo</h2></div><button onClick={this.back}>后退</button><button onClick={this.forward}>前进</button><button onClick={this.go1}>go</button></div>)}
}export default withRouter(Header)

以上是对一般组件Header进行改造,使得它拥有路由的属性和API,这样我们就可以使用路由的前进、后退、跳转等API操作路由了。


小总结

  • withRouter可以加工一般组件,使得它拥有路由组件的属性和API
  • withRouter的返回值是一个新的组件

10、BrowserRouter与HashRouter的区别

1、底层原理不一样

BrowserRouter使用的是H5history API,不兼容IE9及以下版本

HashRouter使用的是URL的哈希值

2、path表现形式不一样

BrowserRouter的路径中没有#,例如:localhost:3000/demo/test

HashRouter的路径包含#,例如:localhost:3000/#/demo/test

3、刷新后对路由state参数的影响

​ (1)BrowserRouter没有任何影响,因为state保存在history对象中

​ (2)HashRouter刷新后会导致路由state参数的丢失

4、备注:HashRouter可以用于解决一些路径错误相关的问题

http://www.lryc.cn/news/66166.html

相关文章:

  • “裸奔”时代下,我们该如何保护网络隐私?
  • c#笔记-方法
  • 054、牛客网算法面试必刷TOP101--堆/栈/队列(230509)
  • 怎么让chatGTP写论文-chatGTP写论文工具
  • springboot 断点上传、续传、秒传实现
  • 2023河南省赛vp题解
  • 港科夜闻|香港科大与香港资管通有限公司签署校企合作备忘录,成立校企合作基金促科研成果落地...
  • Neo4j 笔记
  • 数据库基础应用——概念模型
  • 【学姐面试宝典】前端基础篇Ⅴ——JS深浅拷贝、箭头函数、事件监听等
  • 最新研究,GPT-4暴露了缺点!无法完全理解语言歧义!
  • 商业数据挖掘-第一章-数据探索式分析-1
  • MybatisPlus是否防止SQL注入?
  • 5月第1周榜单丨飞瓜数据B站UP主排行榜(哔哩哔哩平台)发布!
  • 数据的插入删除和更新
  • C# byte[] 与 int 类型互转
  • MySQL---多表联合查询(上)(多表关系、外键约束、学生成绩多表关系、交叉连接查询)
  • 【iOS】—— RunLoop线程常驻和线程保活
  • Springcloud--docker快速入门
  • 基于AT89C51单片机的电子计数器设计与仿真
  • IT程序员如何面对35岁大龄问题?我从公司老板的角度聊聊
  • 【计算机专业漫谈】【计算机系统基础学习笔记】W2-2-2 模运算系统和补码表示
  • vue概述
  • SpringCloud-OpenFeign案例实战
  • ACM - 数学 - 提高(还没学多少)
  • JavaScript class和继承的原理
  • Playwright-python 自动化测试【Anaconda】环境配置
  • 攻防世界-web-simple js
  • 【SpringCloud】初始微服务
  • 均摊时间复杂度