react路由

react路由分三种,这里主要介绍 react-rotuer-dom

  • BrowserRouter:最大的容器,全局只能有一个,route所有的配置都要放在里面才会有效果 Browser(有浏览器的意思) 所以一般直接包裹app.js的根元素。

    • forceRefresh:控制react-router跳转的时候刷新页面或不刷新页面,值为boolean
      使用:<BrowserRouter forceRefresh={true}></BrowserRouter>
  • HashRouter:与BrowserRouter作用相同,不同是以hash的方式进行跳转。

  • Link :<Link to="/name"> 进行跳转

  • Route : <Route path="/name" component={Name} /> 进行匹配

  • NavLink:Link的升级版,自带”active“ class名

    • 属性:activeClassName: 修改高亮的class名
  • Switch:提高效率,优化匹配机制,检测到相同的path之后,不会继续向下传递
    为什么使用Switch?
    重复的path会让两个组件同时显示,所以由两个或两个以上的Route,就需要使用Switch包裹

  • Redirect:一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
    <Redirect to="/home">

  • withRouter:让一般组件实现路由跳转

  • Prompt: React 阻止路由离开(路由拦截)

    <Prompt
    	when={true}
    	message={location => '信息还没保存,确定离开吗?'}
    

/>
```

一般组件与路由组件

  • 写法不同:
    一般组件: </Demo/>
    路由组件:<Route path="/demo" component={Demo}></Route>
  • 接收到props不同
    一般组件:写组件标签时传递的什么,就能收到什么
    路由组件:接收到三个固定的属性
    • history:
      • go
      • goBack
      • goForward
      • push:fn(path,state)
      • replace:fn(path,state)
    • localtion:
      • pathname
      • search
      • state:undefined
    • match:
      • params:{}
      • path:"/about"
      • url:"/about"

精准匹配&模糊匹配

  • 模糊匹配(默认):【输入的路径】必须包含要【匹配的路径】,且顺序要一致
    <NavLink to="/home/a"></NavLink> 添加属性replace={true},开启replace模式
    <Route path="/home" component={Home}></Route>
  • 精准匹配:Route中添加exact属性
    【注意】严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
    值为Boolean ,默认为true
    <Route exact path="/home" component={Home}></Route>

路由传参的三种方式

  • 向路由组件传递params参数

路由链接(传递参数)
<Link to="home/news/detail/1"></Link>
注册路由(声明接收)
<Route path="home/news/detail/:type" component={Detail}></Route>
子组件通过 props.match.params 接收参数

  • 传递search参数

路由链接(会将属性和值一块传递)
<Link to="home/news/detail?id=1&title='标题1'"></Link>
注册路由(正常写即可)
<Route path="home/news/detail" component={Detail}></Route>
子组件通过 props.localtion.serach 可以拿到“?id=1&title=‘标题1’” urlencoded编码字符串
通过简单处理就可以使用
react有自带的方法
import qs from 'querystring
有stringify 和jsonparse 两个方法(和JSON的方法一样)

  • state参数(隐式传参,与组件状态的state无关,不同于vue的隐式传参,刷新可以保留参数)

优点:传递的参数在地址栏中是不显示的
路由链接(对象的方式传递,两个属性pathname和state)
<Link to={{pathname:'home/news/detail',state:{id:1,title:'标题1'}}}></Link>
注册路由(正常写即可)
<Route path="home/news/detail" component={Detail}></Route>
子组件通过 props.localtion.state 接收参数

编码方式(传参形式)?????

urlencoded JSON query params

一般组件实现路由跳转(withRouter)

withRouter可以加工一般组件,让一般组件具备组件所特有的API
withRouter返回值是一个新组建(包含路由组件的API)
import {withRouter} from 'react-router-dom'
导出组件时导出的时withRouter(Header)函数的返回值

BrowserRouter与HashRouter的区别?

1、底层原理不一样:

  • BrowserRouter使用的是H5的history的API,不兼容IE9及以下的版本。
  • HashRouter使用的是URL的哈希值

2、path的表现形式不一样

  • BrowserRouter的路径没有#,例如:localhost:3000/demo/test
  • HashRouter的路径包含#,例如:localhost:3000/#/demo/test

3、刷新后对路由state参数的影响

  • BrowserRouter没有任何影响,因为state保存在history对象中
  • HashRouter刷新后会导致路由state参数的丢失

4、【备注】:HashRouter可以用于解决一些路径错误相关的问题

这里来一个小例子

场景:常见的列表中获取某一条数据的详情。
三个组件:

  • index.jsx :根组件
  • List.jsx:列表组件
  • Detail.jsx:详情组件
//index
import React, { Component } from 'react';
import { NavLink, Route, Switch, Redirect } from 'react-router-dom'

import List from './List';
import Detail from './Detail';
class View extends Component {

  state = {
    list:[]
  }

  render() {
    return (
      <React.Fragment>
        <NavLink to="/list"/>
        <Switch>
          <Route path="/list" component={List}></Route>
          <Route path="/Detail/:type" component={Detail}></Route>
          <Redirect to="/list" />
        </Switch>
      </React.Fragment>
    );
  }
}

export default View;

//List组件
import React, { Component } from 'react'
import axios from '../../unit'
export class List extends Component {

  state = {
    list:[]
  }

  componentDidMount() {
    // 请求数据
     axios('get', '/home/mediareports?', { page_number: 1, page_size: 20 }).then(res => {
      this.setState({ list: res.data.data })
    })
  }

  // 动态传参
  onTarget(id) {
    this.props.history.push(`/detail/${id}`)
  }

  // 渲染页面
  rList() {
    return this.state.list.map(item => (
      <li key={item.id} onClick={()=>{this.onTarget(item.id)}}>
        <p>{ item.main_title }</p>
      </li>
    ))
  }

  render() {
    return (
      <ul>
        {this.rList()}
      </ul>
    )
  }
}

export default List

//Detail组件
import React, { Component } from 'react'
import axios from '../../unit'
export class Detail extends Component {
  
  state = {
    obj:{}
  }

  componentDidMount() {
    // 获取数据
    axios('get', '/home/mediareports?', { page_number: 1, page_size: 20 }).then(res => {
      const data = res.data.data;
      // 拿到params参数
      const id = this.props.match.params.type;
      // 这一块没有获取单个数据接口,所以需要筛选一下
      const obj = data.filter(item => item.id === id)[0]
      this.setState({obj})
    })
  }

  render() {
    let { obj } = this.state
    console.log(obj)
    return (
      <ul>
        <li>标题:{ obj.main_title }</li>
        <li>来源:{ obj.source }</li>
        <li>时间:{ obj.sourceDate }</li>
      </ul>
    )
  }
}

export default Detail

lazy的使用

  • 引入:import React,{ lazy, Suspense } from 'react';
  • 使用:
    const About = lazy(() => import('地址'))
//必须用Suspense 包裹,默认有一个loading回调
<Suspense fallback={<div>loading...</div>}>
  <Route exact path="/" component={Home} />
  <Route path="/about" component={About} />
  <Redirect to="/" />
</Suspense>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值