React路由react-router-dom@5
SPA的理解
- 单页web应用(single page web application SPA)。
- 整个应用只有一个完整的页面。
- 点击页面中的链接不会刷新页面,只会做页面的局部更新。
- 数据都通过ajax请求获取,并在前端异步展示。
什么是路由
1:一个路由就是一个映射关系(key:value)。
2:key作为路径,value可能是functioon或component。
路由分类
1:后端路由
2:前端路由
一、路由的基本使用
关键词:Route Link BrowerRouter
1.明确好界面的导航区、路由区。
2.导航区使用Link标签 属性 <Link to="/home">
首页
3.展示区使用Route标签进行路由匹配 <Route path={/Home} component={ Home }/>
4.<App>
最外层包裹了一个<BrowserRouter>
或<HashRouter>
二、路由组件与一般组件区别
- 写法不同:
一般组件:<Home/>
路由组件:<Route path="/Home" component={ Home }/>
- 存放位置不同:
一般组件:components
路由组件:pages - 接收到的props不同:
一般组件:写组件标签时传递了什么,就收到什么
路由组件:接收到三个固定属性
history------------- 学了
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
push : ƒ push(path, state)
replace: ƒ replace(path, state)
location-------------- 学了
pathname: "/Home"
search: "" 学了
state:undefined 学了
match-----------------
params:{} 学了
path: "/Home"
url:"/Home"
三、NavLink 的封装
1.NavLink可以实现路由链接的高亮,通过activeClassName指定样式类名。
import React, { Component } from 'react'
import { /* Link, */NavLink } from 'react-router-dom'
import "./index.css"
export default class Menu extends Component {
render() {
return (
<div className="menu_box">
<NavLink to="/Home" activeClassName="item_active" className="item">Home</NavLink>
<NavLink to="/About" activeClassName="item_active" className="item">About</NavLink>
</div>
)
}
}
2.标签体内容是一个特殊的标签属性(通过this.props.children获取)
// 封装的 MyNavLink.js
import React, { Component } from 'react'
import "./index.css"
import { NavLink} from "react-router-dom"
export default class MyNavLink extends Component {
render() {
console.log("MyNavLisk_props",this.props)
return (
// <NavLink activeClassName="item_active" className="item" {...this.props}>{ children }</NavLink>
// 优化:props属性传递,以及自带属性 this.props.children 也优化进去了。
<NavLink activeClassName="item_active" className="item" {...this.props}/>
)
}
}
import React, { Component } from 'react'
import MyNavLink from '../MyNavLink'
import "./index.css"
export default class Menu extends Component {
render() {
return (
<div className="menu_box">
<MyNavLink to="Home">首页</MyNavLink>
<MyNavLink to="About">关于</MyNavLink>
</div>
)
}
}
四、Switch的使用
1.通常情况下,path和component是一种一一对应关系。
2.Switch可以提高路由匹配效率(单一匹配)
import React, { Component } from 'react';
import Home from "./pages/Home"
import About from "./pages/About"
import { NavLink,Route,Switch } from "react-router-dom"
import "./App.css"
export default class App extends Component {
render() {
return (
<div className='wrapper'>
<div className="container">
<NavLink to="/Home" activeClassName="item_active" className="item">Home</NavLink>
<NavLink to="/About" activeClassName="item_active" className="item">About</NavLink>
<div className='right'>
<Switch>
{/* 映射关系 /Home--->Home组件 */}
<Route path="/Home" component={ Home}></Route>
<Route path="/About" component={ About}></Route>
</Switch>
</div>
</div>
</div>
)
}
}
学习回顾:2023-10-27
react-router-dom: BrowerRouter/HashRouter、Switch、Route、Link、NavLink;
五、解决多级路径刷新页面样式丢失的问题(新版react已修复)
1、public/index.html 中引入样式时不写 ./ 写 / (常用)
2、public/index.html 中引入样式时不写 ./ 写 %PUBLIC_URL% (常用) ---- react内置写法
3、使用HashRouter
注意:yarn 和 npm的使用 不要混用。
六、路由的严格匹配(exact)与模糊匹配
1、默认模糊匹配(【跳转的路径】必须包含【匹配的路径】且顺序一致) to=“/home/a/b” path=“/home”
2、开启严格匹配<Route exact path="/home" component={Home}>
3、严格匹配不要随意开启,需要再开,有些时候开启会导致无法继续匹配【二级路由】
七、Redirect的使用【重要】
1、一般写在所有路由注册Route的最下方,当所有路由无法匹配时,跳转到Redirect to指定的路由
2、示例代码:
<Switch>
<Route path="/home" component={ Home}></Route>
<Route path="/about" component={ About}></Route>
<Redirect to="/about" />
</Switch>
八、嵌套路由(一样的方式写即可)
1、注册子路由时要写上父路由的path值 /home/message /home/message/detail
2、路由匹配是按照路由的顺序进行的。
九、向路由组件传递参数【重要】
-
params参数 match
路由连接(携带参数):<Link to="/home/message/detail/tom/18">详情</Link>
注册路由:<Route path="/home/message/:name/:age" component={ Detail}>
得到参数:const { name,age} = this.props.match.params; -
search参数 location.search
路由连接(携带参数):<Link to="/home/message/detail?name=爸爸&age=18">详情</Link>
注册路由(不需要接,正常注册即可):<Route path="/home/message/detail" component={ Detail}>
接收参数:const { search } = this.props.location.search;
备注:获取到的参数是urlencoded编码字符串,需要qs解析; -
state参数: pathname state replace
路由连接(携带参数):<Link to={{ pathname:"/home/message/detail",state:v }} key={v.id}><li>{v.title}【详情】</li></Link>
注册路由(不需要接,正常注册即可):<Route path="/home/message/detail" component={ Detail}>
接收参数:const { search } = this.props.location.state; -
总结:
state参数不会在地址栏显示;
三种路由传参都不会丢失;
params与state常用;
十、编程式路由导航【重要】
借助 this.props.history 对象上的API来操作路由的跳转、前进、后退
-this.props.history.push();
-this.props.history.replace();
-this.props.history.goForward();
-this.props.history.goBack();
-this.props.history.go();
// push
let v = {id:2,title:"消息2",content:"李克强同志逝世"};
this.props.history.push(`/home/message/detail?id=${v.id}&title=${v.title}`); // 携带search参数
this.props.history.push(`/home/message/detail/${v.id}/${v.title}`); // 携带params参数
this.props.history.push(`/home/message/detail`,v); // 携带state参数
// replace
this.props.history.replace(`/home/message/detail?id=${v.id}&title=${v.title}`);//携带search参数
this.props.history.replace(`/home/message/detail`,v); // 携带state参数
十一、withRouter的使用
// withRouter可以加工一般组件,让一般组件具有路由组件所特有的API
// withRouter的返回值是一个新组件
import React, { Component } from 'react'
import { withRouter } from 'react-router-dom' // 是一个函数,用于加工一般组件
import "./index.css"
class Header extends Component {
goBack =()=>{
this.props.history.goBack();
}
goForward =()=>{
this.props.history.goForward();
}
go =()=>{
this.props.history.go(-2);
}
render() {
console.log("header-props",this.props)
return (
<div className='header_box'>
<div>头部组件(一般组件)</div>
<div>
<button onClick={ this.goBack }>后 退</button> 
<button onClick={ this.goForward }>前 进</button> 
<button onClick={ this.go }>go</button>
</div>
</div>
)
}
}
export default withRouter(Header)
十二、BrowserRouter与 HashRouter的区别
- 底层原理不一样
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本;
HashRouter使用的是url的hash值0 - path表现形式不一样
BrowserRouter的路径中没有#,例如:localhost:3000/home/message
HashRouter的路径中带有#,例如:localhost:3000/home/#/message - 刷新后对路由state参数的影响
BrowserRouter没有任何影响,因为state保存在history对象中;!!! 常用
HashRouter刷新后会导致路由state参数丢失 !!! - 备注:HashRouter可以用于解决一些路径错误的相关问题