手把手叫你学react-router

94 阅读2分钟

路由 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)

\