路由 react-router-dom
在react-router-dom中,万物皆组件
1、路由基础用法
//router/RouterIndex.js
import React, { Component } from "react";
import { HashRouter, Redirect, Route, Switch } from "react-router-dom";
import PageA from "./";
import PageB from "./";
import PageC from "./";
import NotFound from "./";
export default class RouterIndex extends Component {
render() {
return (
// Switch 相当于js的switch,匹配到就不会再往下走
<Switch>
{/* hash模式 /#/ */}
<HashRouter>
<Route path="/pageA" component={PageA}></Route>
<Route path="/pageB" component={PageB}></Route>
<Route path="/pageC" component={PageC}></Route>
{/* 重定向,模糊匹配'/'的值重定向,带来的问题是所有路由都能匹配到,都发生重定向。需要用Switch解决。但也不会执行下面的NotFound */}
<Redirect from="/" to="/pageA"></Redirect>
{/* 精准匹配 exact:只有'/'才会匹配*/}
<Redirect from="/" to="/pageA" exact></Redirect>
{/* 以上都没有匹配到才跳转的页面 */}
<Route component={NotFound}></Route>
</HashRouter>
</Switch>
);
}
}
//App.js
import React, { Component } from "react";
import MRouter form './router/RouterIndex';
export default class App extends Component {
render(){
return(
<div>
<MRouter/>
</div>
)
}
}
2、嵌套路由
//PageA.js
import { Redirect, Route, Switch } from "react-router-dom";
import ChildA from "./ChildA";
import ChildB from "./ChildB";
function PageA() {
return (
<div>
<div>轮播图</div>
<div>导航栏</div>
{/* 路由配置 嵌套路由 */}
{/* /pageA不能是精准匹配,要保证匹配到/pageA才能匹配子路由 */}
<Switch>
<Route path="./pageA/childA" component={ChildA}></Route>
<Route path="./pageA/childB" component={ChildB}></Route>
<Redirect from="/pageA" to="./pageA/childA"></Redirect>
</Switch>
</div>
);
}
3、路由跳转方式
声明式导航
NavLink要在路由下面才能用
<ul>
<li>
{/* 相当于 <a href="#//pageA/childA"/> */}
{/* activeClassName:定义选中时的类 */}
<NavLink to="/pageA/childA" activeClassName="child-active">
childA
</NavLink>
</li>
<li>
<NavLink to="/pageA/childB" activeClassName="child-active">
childB
</NavLink>
</li>
</ul>
编程式导航
props是<Route/>传过来的
this.props.history.push('/pageAre')
import useHistory from 'react-router-dom'
const history = useHistory()
history.push('/pageAre')
4、动态路由
<Route path="./detail/:id" component={Detail}></Route>
获取id
this.props.match.params.id
5、路由传参
动态路由传参
路由配置:<Route path="./detail/:id" component={Detail}></Route>
传参:history.push(`/detail/${id}`)
获取:this.props.match.params.id
query传参
路由配置:<Route path="./detail" component={Detail}></Route>
传参:this.props.history.push({pathNmae:'/pageAre',query:{id:id}})
获取:this.props.location.query.id
state传参
数据保存在内存中,而不是路径中,复制路径到新页面并不会带参数,不推荐使用
路由配置:<Route path="./detail" component={Detail}></Route>
传参:this.props.history.push({pathNmae:'/pageAre',state:{id:id}})
获取:this.props.location.state.id
6、路由拦截
在render()自定义挂载组件,不是route的子组件,没有经过route给予props的流程,<PageA/>不能获取route的属性props。
function isAuth() {
return localStorage.getItem("token");
}
<Route path="/pageA" render={()=>{
return isAuth() ? <PageA/>:<Redirect to="/login" />
}}></Route>
<Route path="/login" component={Login}></Route>
需要手动加props
function isAuth() {
return localStorage.getItem("token");
}
<Route path="/pageA" render={(props)=>{
return isAuth() ? <PageA {...props}/>:<Redirect to="/login" />
}}></Route>
<Route path="/login" component={Login}></Route>
7、路由模式
hash模式
<HashRouter/>
BrowserRouter
以前常用于多页面项目
BrowserRouter没有#的路径,好看,真正发送请求,后端没有对应的路径处理逻辑,就会404,不好看
<BrowserRouter/>
8、withRouter
<Route/> => <Parent/> => <Child/>
当如上例子拿不到route的路由方法时,可以用withRouter把组件增强,拿到方法
import { withRouter } from 'react-route-dom'
function Child(props){
...
props.history.push('/')
}
export default withRouter(Child)
\