六、React中有关路由内容

一、路由的使用

  1. 安装
npm install react-router-dom
  1. 在原生中使用a标签实现跳转,在react中根据路由连接实现切换组件
  2. App标签的最外层包裹一个BrowseRouter或者HashRouter标签
import { Link,Route } from 'react-router-dom'

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

<!-- 内容展示 -->
<Route path='/home' component={Home}></Route>
<Route path='/about' component={About}></Route>
import { BrowserRouter } from 'react-router-dom';
<!-- 最外层包裹一层BrowserRouter标签 -->
<BrowserRouter>
   <App />
</BrowserRouter>

二、路由组件和一般组件的区别

  1. 写法不同:
	一般组件:<Demo/>
	路由组件:<Route path="/demo" component={Demo}/>
  1. 存放位置不同:
一般组件:components
路由组件:pages

3.接收到的props不同:

一般组件:写组件标签时传递了什么,就能收到什么
路由组件:接收到三个固定的属性
	history:
		go: ƒ go(n)
		goBack: ƒ goBack()
		goForward: ƒ goForward()
		push: ƒ push(path, state)
		replace: ƒ replace(path, state)
	location:
		pathname: "/about"
		search: ""
		state: undefined
	match:
		params: {}
		path: "/about"
		url: "/about"

三、NavLink

  1. 当使用NavLink而不是Link时,点击哪个按钮,className中就会默认追加一个active属性
  2. NavLink中可以通过activeClassName来指定追加的属性名
<NavLink activeClassName="peiqi" className="list-group-item" to="/home">Home</NavLink>
<NavLink className="list-group-item" to="/about">About</NavLink>

四、NavLink的封装

  • 如果页面中需要多个NavLink标签,此时页面中会出现许多的冗余部分,如样式等,那么可对NavLink进行一层封装,将公共的部分内容封装起来,得到一个MyNavLink标签,该标签中内容即为这些标签中不同的内容
  • MyNavLink与NavLink的形式保持一致,那么如何将标签体中内容传递给NavLink呢?NavLink中内置了一个children属性,该属性的属性值即为标签体中的内容
<!-- 封装的NAVLink内容 -->
<NavLink activeClassName="peiqi" className="list-group-item" {...this.props}/>
<!-- 对封装后得到的MyNavLink的使用 -->
<MyNavLink to="/about">About</MyNavLink>
<!-- 相当于NavLink中的如下用法 -->
<!--<NavLink activeClassName="peiqi" to="/home" className="list-group-item" children="Home"/>-->
<MyNavLink to="/home">Home</MyNavLink>
  • 使用{…this.props}可以避免当MyNavLink中一次性要传递多个props时造成NavLink中接收过于麻烦的情况
  • 标签体内容是一个特殊的标签属性,通过this.props.children可以获取到标签体的内容

五、Switch的用法

  1. 在使用路由时,如果存在多个路由路径相同,则此时对用的路由组件都会展示,那么这样会导致一个效率问题。当代码在执行时,存在多个相同路径,不同路由组件时,会在找到第一个后,继续向下查找有没有相同路径的路由组件,这样会导致代码的效率问题
  2. 使用Switch标签可以解决这个问题,在所有的路由组件外包裹一层Switch标签,此时,当匹配到第一个路由组件时,就不会继续再向下进行匹配
import { NavLink, Route, Switch } from 'react-router-dom'
<Switch>
     <Route path='/about' component={About}></Route>
     <Route path='/home' component={Home}></Route>
     <Route path='/about' component={A}></Route>
     <Route path='/about' component={B}></Route>
     <Route path='/about' component={C}></Route>
</Switch>
  • 总结:通常情况下,path和component是一一对应的关系,Switch可以提高路由匹配效率(单一匹配)

六、解决样式丢失的问题

  • 当页面中的路由路径是多级的结构时,此时一刷新页面,就会导致页面中的样式丢失问题:页面中使用bootstrap.css样式时,当页面处于多级路由的情况下,点击刷新,此时浏览器再次返回的页面没有bootstrap.css样式
  • 导致原因:当路径存在问题时,会直接将public文件下中的index.html中的内容返回,导致样式丢失
  • 解决方法:

方法一:

<link rel="stylesheet" href="./bootstrap.css">
改为:
 <link rel="stylesheet" href="/bootstrap.css">
 去掉了.,.表示当前文件下

方法二:

<link rel="stylesheet" href="./bootstrap.css">
改为:
<link rel="stylesheet" href="%PUBLIC_URL%/bootstrap.css">
%PUBLIC_URL%表示public绝对路径

方法三:将BrowserRouter改为HashRouter
其中方法一和方法二是常用方法,且方法二只适用于React脚手架中使用

七、路由的模糊匹配和严格匹配

  1. 模糊匹配(默认
  • to中的内容要包含path,且path中的内容必须是在第一个,否则当第一个内容不匹配时,则不会在对后面的内容进行匹配
  • 默认是模糊匹配
  1. 严格匹配
  • 在Route标签中添加exact={true}属性,此时即开启严格匹配模式,要求to和path中的内容一致
  • 也可以直接使用exact
  • 不要随便开启严格匹配,需要再开,有时候开启会导致无法继续匹配二级路由
<Route exact={true} path='/about' component={About}></Route>
<Route exact  path='/about' component={About}></Route>

八、Redirect的使用

<Switch>
	<Route exact={true} path='/about' component={About}></Route>
	<Route  path='/home' component={Home}></Route>
	<Redirect to="/home"/>
</Switch>
  • Redirect放在所有路由注册的后面,当所有的路由都没有匹配成功时,跳转到Redirect指定的路由
  • 可实现当页面一加载时,默认路由选中的效果

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

<!-- 利用ES6中的模板字符串传递params参数 -->
<!-- 路由链接——携带参数 -->
<Link to={`/home/messages/detail/${messageOj.id}/${messageOj.title}`}>{messageOj.title}</Link>
<!-- 接收参数,通过:XXX的形式 -->
<!-- 注册路由——声明参数 -->
<Route path="/home/messages/detail/:id/:title" component={Detaildata}/>
  • 注意:这里的传递给Detaildata组件中的params参数,在Detaildata中通过this.props.match.params获得
  • 可以利用解构{id,title} = this.props.match.params获得传递的id和title

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

  1. 与传递params参数相比,search参数的接收更容易,但是获得确更麻烦。params参数获得的是一个已经整理好的对象,但是search却是一个字符串,需要再进行加工整理
  2. 传递参数:
<Link to={`/home/messages/detail/?id=${messageOj.id}&title=${messageOj.title}`}>{messageOj.title}</Link>
  1. 接收参数:不用像search那样声明接收参数
<Route path="/home/messages/detail" component={Detaildata}/>
  1. 整理参数:用于search参数传递是urlencoded编码字符串(?key=value&key=value),因此还需要进行特殊整理
  • 引入querystring库,该库时react脚手架已经下载好的,直接引用即可
import qs from 'querystring'
该库中有两个函数,一个是stringify:将对象整理成key=value&key=value的形式
如:{name:'Tom', age: 18}通过qs.stringify()处理变成name=Tom&age=18
一个是parse:将字符串解析成对象的形式
  • 通过this.props.location.search.slice(1)获取传递的search参数,注意这里的slice(1)是为了去掉字符串前面的?
<!-- 传递参数  -->
<Link to={`/home/messages/detail/?id=${messageOj.id}&title=${messageOj.title}`}>{messageOj.title}</Link>
<!-- 接收参数(不用声明接收,正常注册路由即可)  -->
<Route path="/home/messages/detail" component={Detaildata}/>
//处理参数
const {data} = this.state
const str = this.props.location.search.slice(1)
const {id, title}  = qs.parse(str)

十一、向路由传递state参数

  1. 与前面的两种参数相比,传递state参数时,搜索栏中不显示携带的信息,即信息被隐藏
  2. 路由链接——携带参数
<Link to={{pathname:'/home/messages/detail',state: {id:messageOj.id,title:messageOj.title}}}>{messageOj.title}</Link>
以对象的形式传递
  1. 注册路由(无需声明,正常注册即可)
<Route path="/home/messages/detail" component={Detaildata}/>
  1. 接收参数:this.props.location.state
  2. 当向路由传递state参数时,刷新也可以保留住参数

十二、如何开启replace模式

  • 当路由链接开启replace模式时,点击该链接,此时栈顶的路由记录会被替换掉
  • 如何开启:在路由链接中添加replace={true}或者replace属性

十三、编程式路由导航

history:
		go: ƒ go(n)
		goBack: ƒ goBack()
		goForward: ƒ goForward()
		push: ƒ push(path, state)
		replace: ƒ replace(path, state)
  1. replace的实现

1.replace和传递params参数

//定义
onClick={() => this.clickReplace (id,title)}
//实现
clickReplace = (id,title) => {  this.props.history.replace('/home/messages/detail/${id}/${title}');}
  1. replace和传递search参数
//定义
onClick={() => this.clickReplace (id,title)}
//实现
clickReplace = (id,title) => {  this.props.history.replace('/home/messages/detail/?id=${id}&title=${title}');
  1. replace和传递state参数:push: ƒ push(path, state)
//定义
onClick={() => this.clickReplace (id,title)}
//实现
clickReplace = (id,title) => {  this.props.history.replace('/home/messages/detail',{id,title});
  1. push的实现
  • 和replace使用过程一样,但是使用this.props.history.push()
  1. 其他:
this.props.history.goBack()——后退
this.props.history.goForward()——前进
this.props.history.go(num):num为正时,表示前进,为负时,表示后退

十四、withRouter

  1. 当在一般组件中要使用路由组件中的一些特有的API时,如:在一般组件中通过this.props.history来进行调用时,由于路由组价和一般组件中的this.props是不一样,此时会报错。那么如何解决这个问题呢?利用withRouter可以解决
  2. 作用:withRouter可以加工一般的组件,让一般组件具备路由组件所特有的API。withRouter是个函数,接收的参数为一般组件,用于解决在一般组件中使用路由组件中的API的问题。其返回值是一个新的组件
//1.引入
import {withRouter} from 'react-router-dom'
//2.定义一般组件
class XXX extends React.Component {
}
//3.将一般组件作为参数传入
//一般组件:<XXX />
export default withRouter(XXX)

十五、BrowserRouter和HashRouter的区别

  1. 底层原理不一样:
  • BrowserRouter使用的是H5的history API,不兼容IE9及以下版本
  • HashRouter使用的是URL的哈希值
  1. path表现形式不一样:
  • BrowserRouter的路径中没有#
  • HashRouter的路径包含#
  1. 刷新后对路由state参数的影响:
  • BrowserRouter没有任何影响,因为state保存在history对象中
  • HashRouter刷新后会导致路由state参数的丢失
  1. HashRouter可以用于解决一些路径错误相关的问题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值