react笔记_10react路由
目录
- 什么叫做路由?
- 路由组件与一般组件区别
- react中配置路由
- [1] 下载
- [2] 注册路由
- Switch
- [3] 导航区(路由跳转)
- 编程式导航
- [4] 路由出口
- [5] 路由重定向
- [6] 路径的模糊匹配与严格匹配
- [7] 嵌套路由
- [8] 路由传参
- 1.search参数
- 2.state参数
- 3.params参数
- 编程式导航路由传参
- 路由配置封装
什么叫做路由?
一个路由就是一个映射关系(key:value)
key为路径, value可能是function或component
- function: 后端路由,用来处理客户端提交的请求;
- component:前端路由,用于展示页面内容;
路由组件与一般组件区别
- 写法不同:
- 一般组件:
<Demo/>
- 路由组件:
<Route path="/demo" component={Demo}/>
- 一般组件:
- 存放位置不同:
* 一般组件: components
* 路由组件: pages - 接收到的props不同:
- 一般组件: 写组件标签时传递了什么,就能收到什么
- 路由组件: 接收带三个固定的属性
react中配置路由
在react中使用 react-router-dom(插件) 来进行路由的配置
[1] 下载
使用npm i react-router-dom
命令下载 路由插件;
- 报错:A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .
- 原因:我下载时使用的命令是npm i react-router-dom 下载的是最新版本(6版本)—语法不兼容了
- 解决:
npm i react-router-dom@5.2.0
下载6以下的版本
[2] 注册路由
在下载了 react-router-dom 插件之后,就可以通过 react-router-dom包引入 Route
组件注册路由。
Route组件包含以下属性
path
: 路由的路径component
: 组件exact
: 是否进行严格匹配(默认模糊匹配)
以下就注册了一个 Home 组件 ,组件路径为/home。
// [1]引入注册路由组件
import {Route} from 'react-router-dom'
// [2] 引入组件
import Home from '../src/pages/Home'
// [3] 注册组件
<Route path='/home' component={Home}></Route>
Switch
在注册路由时如下:可能有两个甚至多个的路由注册,通过 下面代码 注册路由 当path变为/home时 路由出口的位置展示哪个组件-- Home组件orTest组件or两个都展示?
<Route path='/about' component={About}/>
<Route path='/home' component={Home}/>
<Route path='/home' component={TEst}/>
- 答案:两个都展示
- 原因:路由的匹配规则为->
从第一个开始匹配直至最后一个,即使找到对应路由也不会停止寻找
; - 问题:正常情况下,我们配置路由和路径时是 一一对应 的关系,因此这样的匹配规则是非常浪费性能的;
- 解决:将 注册路由的代码 使用 switch 组件包裹 ;
使用switch包裹后的匹配规则: 从第一个开始寻找,找到一个对应的路由则匹配结束
;
通过 下面代码 注册路由 当path变为/home时仅仅展示Home组件
<Switch>
<Route path='/about' component={About}/>
<Route path='/home' component={Home}/>
<Route path='/home' component={Nested}/>
</Switch>
[3] 导航区(路由跳转)
在下载了 react-router-dom 插件之后,就可以通过 react-router-dom包引入 Link
、NavLink
组件进行导航(路由跳转)。
Link组件包含以下属性
to
: 点击之后需要跳转的路由路径replace
:是否覆盖当前路径
NavLink组件包含以下属性
to
: 点击之后需要跳转的路由路径activeClassName
: 点击之后的样式的类名replace
:是否覆盖当前路径
以下就注册了一个 Home 组件 ,组件路径为/home;配置了一个跳转到home组件的链接,当点击“点我跳转到home组件”页面路径就变为/home了。
import {Component} from 'react'
import Home from '../src/pages/Home'
import {Link, Route} from 'react-router-dom'
export default class App extends Component {
render(){
return (
<div>
<Link to='/home'>点我跳转到home组件</Link>
<Route path='/home' component={Home}></Route>
</div>
)
}
}
编程式导航
除了上述通过组件进行路由跳转,也可以通过编程式导航进行路由跳转;
语法-借助prosp.history
对象上的API对操作路由跳转、前进、后退
this.prosp.history.push()
this.prosp.history.replace()
this.prosp.history.goBack()
this.prosp.history.goForward()
this.prosp.history.go()
[4] 路由出口
路由分为两类:
Browser
路由: 路径和正常路径相同(与vue中history路由原理相同)Hash
路由:路径中存在#(与vue中hash路由原理相同)
路由出口
- 若是Browser路由则路由出口为
<BrowserRouter>
; - 若是Hash路由则路由出口为
<HashRouter>
;
下面配置表示该项目使用的是 Browser路由:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>
);
下面配置表示该项目使用的是 Hash路由:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { HashRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<HashRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</HashRouter>
);
[5] 路由重定向
<Switch>
<Route path='/about' component={About}/>
<Route path='/home' component={Home}/>
<Route path='/nested' component={Nested}/>
</Switch>
以上是注册的几个路由,但是一进入页面时,匹配不到任何的路由,此时若是我们想进入页面(url为空)时默认展示home组件的内容,可以使用路由重定向。
Redirect组件包含以下属性
to
: 路由重定向的路径
在下载了 react-router-dom 插件之后,就可以通过 react-router-dom包引入 Redirect
组件进行路由重定向。
Redirect写在注册路由的下方(兜底)—当所有路由都匹配不上时 自动跳转到Redirect设置的路径上。
<Switch>
<Route path='/about' component={About}/>
<Route path='/home' component={Home}/>
<Route path='/nested' component={Nested}/>
<Redirect to='/home' />
</Switch>
在上方路径匹配后,当在浏览器输入路径 http://localhost:3000,默认路径会变为 http://localhost:3000/home
[6] 路径的模糊匹配与严格匹配
在路由跳转时,我们需要将 Link组件的to属性值 与 Route组件的path属性值进行匹配
- 严格匹配:只有编写路由路径的link和注册路由的path 一模一样时才能成功显示对应的路由
- 模糊匹配:会将to属性值以 / 划分 为 home a b, path属性同样以/进行划分为home,然后将path划分值按照顺序和to属性值进行匹配
只要path属性值匹配完毕且全部对应
(to属性值存在剩余没有关系)则称为匹配
模糊匹配举例说明
<Link to='/home'></Link>
<Route path='/home' component={Home}/>
可以成功跳转
<Link to='/home/a/b'></Link>
<Route path='/home' component={Home}/>
可以成功跳转
<Link to='/a/home/a/b'></Link>
<Route path='/home' component={Home}/>
不能成功跳转
注意:不要随意开启严格匹配,否则会出现一些问题 比如嵌套路由无法匹配
[7] 嵌套路由
首先明确一点:路由的匹配是按照注册路由的顺序进行
的.
举例说明
在App.vue(跟组件)注册了 Home路由和About路由,在Home组件注册了 Sun1和Sun2 两个子路由
- App.jsx
import About from '../src/pages/About' import Home from '../src/pages/Home' import {Link,NavLink, Route,Switch,Redirect} from 'react-router-dom' import {Component} from 'react' export default class App extends Component { render(){ return ( <div> <div className='left'> <Link to='/about'>About</Link> <br /> <NavLink activeClassName='active' to='/home'>Home</NavLink> <br /> <Link to='/home/sun1'>sun1</Link> <br /> <Link to='/home/sun2'>sun2</Link> </div> <div className='right'> <Switch> <Route path='/about' component={About}/> <Route path='/home' component={Home}/> <Redirect to='/home' /> </Switch> </div> </div> ) } }
- Home组件
import React, { Component } from 'react' import {Route,Switch} from 'react-router-dom' import Sun1 from './New' import Sun2 from './New2' export default class Home extends Component { render() { return ( <div> 我是home组件 <Switch> <Route path='/home/sun1' component={Sun1}></Route> <Route path='/home/sun2' component={Sun2}></Route> </Switch> </div> ) } }
- 当进入页面的路径为/home/sun2时
- 渲染过程
- 在渲染过程中先渲染App.vue, 发现页面有注册路由-> 进行路由匹配
- 经过模糊匹配 Home组件被匹配(/home) -> 渲染home组件
- 在渲染过程中,发现Home组件中也进行了路由注册->进行路由匹配
- 经过模糊匹配 发现与Sun2组件完全对应(/home/sun2), 渲染Sun2组件
- 通过匹配过程我们也可以看出
注册子路由时要写上父路由的path值
不然最初的匹配就失败!
[8] 路由传参
通过路由向组件传参一共有三种方式
1.search参数
- 传参
<Link to='url?参数名=参数值&参数名=参数值'></Link>
- 接收
this.props.location.search // String
- 举例说明
在子组件接收<Link to='/home/sun1?name=111&age=18'>sun1</Link>
接收到的是 urlencoded编码字符串,需要借助querystring解析console.log('search参数', this.props.location.search) // search参数 ?name=111&age=18
- querystring插件使用
- [1] 下载
使用npm install querystring -D
命令下载 - [2] 引入
import qs from 'querystring'
- [3] 解析参数
console.log('search参数', qs.parse(this.props.location.search.split('?')[1]) ) // search参数 {name: '111', age: '18'}
- [1] 下载
2.state参数
- 传参
<Link to={{pathname:url, state:{参数名:参数值}}}></Link>
- 接收
this.props.location.state // Object
- 举例说明
在子组件接收<Link to={{pathname:'/home/sun1', state:{name:'111', age:18}}}>sun1</Link>
console.log('state', this.props.location.state ) // state {name: '111', age: 18}
3.params参数
- 传参
<Link to=‘url/参数值/参数值’></Link>
- 声明
<Route path="/demo/test/:参数名/:参数值" component={Test}/>
- 接收
this.props.match.params // Object
- 举例说明
<Link to='/home/sun1/111/18'>sun1</Link>
在子组件接收<Route path='/home/sun1/:name/:age' component={Sun1}></Route>
console.log('state', this.props.match.params ) // params {name: '111', age: '18'}
编程式导航路由传参
// search参数
this.props.history.push('url?参数名=参数值')
// state参数
this.props.history.push(url,{参数名,参数值})
// params参数
this.props.history.push('/home/message/detail/参数值')
路由配置封装
111
以下代码的含义是当路径为/about时就跳转到About组件
<Route path='/about' component={About}/>
<Route path='/about' render={(props)=>{
// 逻辑跳转
// 如果符合条件->跳转到About组件
if(xxx){
return <About />
}else{
return <Redirect to='/login' />
}
}}/>