一、React 路由
1 什么是路由?
路由是根据不同的
url
地址展示不同的内容或页面。一个针对
React
而设计的路由解决方案、可以友好的帮你解决React components
到URL
之间的同步映射关系
2 路由安装
npm install react-router-dom@5
3 路由使用
<Redirect from="/" to="/home"/>
- exact 精确匹配(Redirect即使使用了exact,外面还要嵌套Switch来用)
- Warning:Hash history cannot PUSH the same path;a new entry will not be added to the history stack,这个警告只有在hash模式会出现。
import React from 'react'
// BrowserRouter 没有#的路径,好看,真正朝后端发送请求要页面,后端没有对应的路径处理路径,就会404,不好看
import { HashRouter, Route, Redirect, Switch } from 'react-router-dom'
import Two from './Two'
import Three from './Three'
import NotFound from './NotFound'
export default function One() {
return (
<HashRouter>
<Switch>
<Route path="/two" component={Two} />
<Route path="/Three" component={Three} />
{/* Redirect 是模糊匹配,为了避免则需要套在Switch里 */}
<Redirect from="/" to="/two" exact />
{/* 精确匹配 exact */}
<Route component={NotFound} />
</Switch>
</HashRouter>
)
}
4 路由跳转方式
- 声明式导航
<NavLink to="/one" activeClassName="active">One</NavLink>
<NavLink to="/two" activeClassName="active">Two</NavLink>
<NavLink to="/Three" activeClassName="active">Three</NavLink>
- 编程式导航
// 函数组件
props.history.push("/one")
// 类组件
this.props.history.push("/one")
// hooks router自带的方法
import { Redirect, Route, Switch, useHistory } from 'react-router-dom'
const history = useHistory()
history.push('/three')
5 路由传参
//(1)
<Route path="/two/:id" component={Two} />
<NavLink to="/two/1">点击</NavLink>
console.log(props.match.params.id)
//(2)
props.history.push({ pathname: '/three', query: { id: 1 } })
console.log(props.location.query.id)
//(3)
props.history.push({ pathname: '/three', state: { id: 1 } })
console.log(props.location.state.id)
建议使用第一种方案,第二种和第三种方案在第一次加载时会报错。
Cannot read properties of undefined (reading 'id')
6 路由拦截
// 以下两种方法效果相同
<Route path="/three" render={() => <Two/>} />
<Route path="/two" component={Two} />
// 满足isAdmin()条件进入<Three />,不满足进入<Four />
<Route path="/three" render={() => {
return isAdmin() ? <Three /> : <Four />
}} />
// 等于
<Route path="/three" render={() => {
return isAdmin() ? <Three /> : <Redirect to="/four" />
}} />
// 传参
<Route path="/three" render={(props) => {
return isAdmin() ? <Three {...props} /> : <Redirect to="/four" />
}} />
7 子组件使用父组件的路由方法
因为想要实现路由跳转需要有history属性,子组件可以继承父组件的
prop.history
从而获得history属性。
import React from 'react'
export default function One(props) {
return (
<div><OneChild {...props} /></div>// 通过{...props}把父组件的路由属性传递给子组件。
)
}
function OneChild(props) {
return <div>
<button onClick={() => {
props.history.push("two")
}}>点击</button>
</div>
}
// 也可以直接使用NavLink实现路由跳转
<NavLink to="/two">点击</NavLink>
// 或者使用下面的withRouter方法
8 withRouter的应用与原理
可以避免使用
{...props}
对子组件一级一级往下传。
import React from 'react'
import { NavLink, withRouter } from 'react-router-dom'
export default function One(props) {
return (
<div><WithOneChild /></div> // 未使用{...props}
)
}
function OneChild(props) {
console.log(props)
return <div>
<button onClick={() => {
props.history.push("two") // 可以使用history方法
}}>点击</button>
</div>
}
const WithOneChild = withRouter(OneChild)