React Router

1,080 阅读6分钟

1. react-router包的下载

npm install react-router-dom -S

2. 基本使用

2.1 react-router主要的API

  1. 【HashRouter】与【BrowserRouter】,两个API是两种路由模式,被包裹,意味着当前组件开启了路由
  2. 【Link】与【NavLink】,两个API用于路径跳转,最终会被渲染成【a】标签,可以通过【to】属性,设置路由跳转路径
  1. 【Route】用于路径的匹配,被匹配到的路径,就会显示指定的页面
    • 【path属性】,用于设置路径匹配
    • 【component属性】,路径匹配成功后,要显示的组件。
    • 【exact属性】,精准匹配,只有精准哦匹配完整完全一样的路径,才会渲染组件
import {HashRouter,Link,Route} from 'react-router-dom'
import Home from './Home.js'
import List from './List.js'

function App () {
  return (
    <div>
      <HashRouter> 【 开启路由 hash模式 】
      	<Link to="/" >首页</Link>
        <Link to="/list">列表</Link>
        
        <Route path="/" component={Home} exact /> 【 精准的匹配,只有匹配到 / 才能进行展示 】
        <Route path="/list" component={List} />
      </HashRouter>
    </div>
  )
}
export default App

function Home() {
  return (
    <div>Home</div>
  )
}
export default Home 

function List() {
  return (
    <div>List</div>
  )
}
export default List 

3. 路由匹配规则Switch

  1. 【Switch】组件将Route进行包裹,目的是只有匹配到的路由组件,才被显示,匹配不到的是不显示
  2. Switch: 如果一个组件上出现多了相同的路由匹配路径,在跳转时,会同时显示,使用switch就可以打断重复的组件被显示
import { Switch,Route } from 'react-router-dom'

<Switch>
     <Route  path="/home" component={Home} />
     <Route  path="/list" component={List}/>
     <Route  path="/list" component={List}/>
</Switch>
  1. 如果所有的路由都没有被匹配到,就显示默认路由组件
【防止用户在访问组件时,在地址后面,添加其他,但是被匹配的组件就会显示,所以需要展示404组件】

<!--在组件的后面设置exact-->
<Route  path="/list" component={List} exact/>
<!--设置的时候,无需设置匹配路径-->
<Route  component={ NotDefined } />

4. 路由跳转(原生JS)与重定向

在某一些情况下,当前用户处于未登录的状态,但是他访问了登陆后访问的页面,这时就需要重定向,让用户跳转到登录的页面

4.1 原生

<!-- 方式一:引入包使用,使用方法 -->
import { createHashHistory } from 'history'
<button onClick={ () => {createHashHistory().push('/home')} }>点击跳转首页</button>

<!-- 方式二: 不需要使用引入的包 只有是当前组件是路由组件的时候,才会有history属性 -->
<button onClick={ ()=> {this.props.history.push('/home') } }>点击跳转首页</button>

4.2 react-router-dom [Redirect] API

<!-- 引包 -->
import { Redirect } from 'react-router-dom'
【设置成标签,to属性就是要重新跳转的页面地址】
<Redirect to="/list" />

5. 路由嵌套

也就是当前组件内,有两个按钮,进行跳转,但是不希望去跳转,只是两个组件之间来回切换,而不是路由跳转

举例pc端的网易云音乐,默认展示发现音乐,在发现音乐里面,下面还有【推荐,排行榜,歌单】等等,通过点击每一个,都是展示对应的内容,再点击的时候发现是在发现页面里面尽心展示的,并没有跳转到其他的页面,所以【推荐】以及其他的都是【发现页面】里的二级,不跳转到其他页面,只在发现音乐里面展示对象的内容

App组件 】
import React, { PureComponent } from 'react'
import Item from './Item'
import {Switch,Link,Route} from 'react-router-dom'

class App extends PureComponent {
  render() {
    return (
      <div>
        <Link to="/item">发现页面</Link>
        <Switch>
          <Route path="/item" component={Item}/>
        </Switch>
      </div>
    )
  }
}

export default App
【 item组件,并且组件内部是有二级组件 】
import React from 'react'
import {Switch,Link,Route} from 'react-router-dom'

import Home from './Components/Home'
import About from './Components/About'
import List from './Components/List'

function Item() {
  return (
    <div>
      <Link to="/item">我的</Link>
      <Link to="/item/about">--关于--</Link>
      <Link to="/item/list">列表</Link>

      <Switch>
        <Route path="/item" component={Home} exact/>
        <Route path="/item/about" component={About}/>
        <Route path="/item/list" component={List}/>
      </Switch>
    </div>
  )
}

export default Item

在某些情况,当编写路由的时候,将【一级路由】的【url以及path】不小心改掉了,导致组件内的二级路由不能访问,设置动态的【一级路由】

import React,{Component} from 'react'

class Item extends Component{
	 render(props) {
    console.log(this.props);
    return (
      <div>
        <div>
          <Link to={`${this.props.match.url}/inner`}>国内新闻</Link>----
          <Link to={`${this.props.match.url}/outer`}>国际新闻</Link>
        </div>
        <div>
          <Route path={`${this.props.match.path}/inner`} component={ inner }></Route>
          <Route path={`${this.props.match.path}/outer`} component={ outer }></Route>
        </div>
      </div>
    )
  }
}
export default Item

6. 动态路由参数

使用【params】传递参数

【相当于vue的router文件内部配置】
<Route path="/detail/:id" component={ Detail } />
 
【从相当于某一个组件通过拼接路径方式进行传参】
<Link to="/detail/1">文章标签</Link>

【组件内部获取传递过来的数据 ,通过使用props,因为使用了HashRouter,会生成一个对象】
<div>{ this.props.match.params.id }</div>

使用【query】进行参数传递

<Link to={{ pathname: '/home' ,query: { id:111 }}}>前往首页</Link>

【 组件中获取传递过来的数据 】
this.props.location.query

【查询参数传递参数】

<Link to="/home?type='nihao'">前往首页</Link>

<!--使用qs对数据进行处理,并且通过第二个参数,对分隔符进行处理-->
qs.parse(this.props.location.search,{ignoreQueryPrefix:true})

例如商品详情页的参数传递,如果父组件里面没有使用【link】的方式跳转,携带参数,可以使用【history.push】进行路由跳转并且带参数,这个是当使用了【HashRoute】的时候生成的。

【 home 】
import React,{Component} from 'react'

class App extends Componet{
  render() {
    return (
      <div>
        <button onClick={this.goList.bind(this}>跳转到list,并且携带参数</button>
      </div>
    )
  }
  goList() {
  	this.props.history.push('/list/:1') 【 01.方式一 】
    this.props.history.push({pathname: '/list/1'}) 【 02.方式二 】
  }
}

【 list拿到参数 】
console.log(props.match.params.id)

7. 路由守卫与路由守组件

7.1 基本使用

  1. 路由守卫的作用,当跳转组件的时候,要去做一些验证,比如说验证【用户是否登录】,如果用户没有登录,就要重新定向到登录界面
  2. 当某一个路由需要设置路由守卫,就需要将【Route】里面的【component】替换成【render】,通过设置【render】判断是否需要跳转
  1. 【render】属性,值是一个方法
<Route path="/item/list" render={(props) => { 【 props存放的是路由信息对象 】
  if(user) { 【 如果用户登录了,就要跳转 】
     return <List {...props}  /> 【 要跳转到的组件 】
  } else {
  	return <Redirect to="/home" /> 【 如果没有登录,就要重新定向到首页或者是登录页面 】
  }
}}/>

7.2 路由组件

当很多条路由需要配置路由守卫,那么代码就要书写很多,所以将路由配置封装成一个组件,需要设置路由守卫的调用组件,并将参数传递给路由组件

【 路由组件封装 】
import React, { PureComponent } from 'react'
import { Route,Redirect } from 'react-router-dom'

class RouterItem extends PureComponent {
  state = {
    user:false,
  }
  render() {
    const { component: Component, ...residue } = this.props  【 component,是传递过来的组件,residue是所有路由信息 】
    return (
      <div>
        <Route {...residue} render={props => {  【 residue包含path以及其他参数,依次的传递给Route 】
          
          if(this.state.user) {
            return <Component {...props}/>
          } else {
            return <Redirect to="/item" />
          }

        }} />
      </div>
    )
  }
}

export default RouterItem

【 被设置的路由组件 】
<RouterItem path="/item/list" component={List}/> 【调用封装好的路由组件,信息正常书写,会以props的形式传递给路由组件进行设置】

8. 路由懒加载

  1. 【为什么要做懒加载】,使用懒加载,可以优化网站首屏加载的速度
  2. 【怎么设置懒加载】,通过第三方插件库
【 下载包 】
npm i @loadable/component

【 使用 】
import LoadableComponent from '@loadable/component'
const Home =  LoadableComponent(() => import('./components/Home'))

9. 非路由组件的参数传递 (待更新)

  1. 在某种情况下,有一些组件,是不需要配置路由的,他是可以直接在组件里面进行引入使用的

10. react-router-config[简化路由配置]

  1. 下载安装包
npm install react-router-config --save
  1. 使用【react-router-config】
const routes = [
  {
    patch: "路径",
    component: 组件,
    exact: true /* 精准匹配 */
  },
  {
    path: '/about',
    component: 组件,
    routes: [ 【 配置子路由 】
      {
	path: '/about',
        component: 组件,
        exact: true /* 精准匹配 */
      }
    ]
  }
]
    
export default routes

【 渲染路由组件 】
import { renderRoutes } from 'react-router-config'
import routes from './routes'

function App() {
  return (
    <div>
      {renderRoutes(routes)} 【 渲染路由组件 】
      {renderRoutes( props.route.routes )} 【 嵌套路由的渲染 】
    </div>
  )
} 

export default App

10.1 其他的路由知识点

  1. 路由配置重定向的配置
import React from 'react';
import { Redirect } from "react-router-dom";

const routes = [
  {
    path: "/",
    exact: true,
    render: () => (  【 使用render函数重新渲染重定向组件 】
      <Redirect to="/discover"/>
    )
  },
  {
    path: "/discover",
    component: HYDiscover,
  }
]