React05_React-Router

5 react-router

5.1 相关理解

  • SPA的理解:
    1. 单页Web应用(single page web application, SPA)
    2. 整个页面只有一个完整的页面
    3. 点击页面中的连接不会刷新页面,只做页面的局部更新
    4. 数据都需要通过ajax请求获取,在前端异步展现
  • 路由的理解
    • 什么是路由
      1. 一个路由就是一个映射关系{key : value}
      2. key 为路径, value 可能是 function 或 component
    • 路由的分类
      1. 后端路由
        • 理解:value 是 function, 用来处理客户端提交的请求
        • 注册路由:router.get(path, function(req, res))
        • 工作过程:当node接收到一个请求时,根据请求路径找到匹配的路由,调用路由中的函数来处理请求,返回响应数据
      2. 前端路由
        • 浏览器端路由,value 是 component,用于展示页面内容
        • 注册路由:<Route path="/test" component={Test}>
        • 工作过程:当浏览器的path变为/test时,当前路由组件就会变为Test组件
  • react-router 的理解
    1. react 的一个插件库
    2. 专门用来实现一个SPA应用
    3. 基于react的项目基本都会用到此库

5.2 react-router-dom 相关API

-- 安装
yarn add react-router-dom
npm install --save react-router-dom

5.3 基本路由使用

  • 路由组件与一般组件

    1. 写法不同:

      • 一般组件: <Demo />
      • 路由组件: <Route path="/demo" component={Demo} />
    2. 存放位置不同:

      • 一般组件: components
      • 路由组件:pages
    3. 接收到的props不同:

      • 一般组件:写组件标签时传递了什么,就能收到了什么

      • 路由组件:接收到三个固定属性

        history:
            go: ƒ go(n)
            goBack: ƒ goBack()
            goForward: ƒ goForward()
            push: ƒ push(path, state)
            replace: ƒ replace(path, state)
        location:
            pathname: "/about"
            search: ""
            state: undefined
        match:
            params: {
                  
                  }
            path: "/about"
            url: "/about"
        
  • NavLink的使用

    • 点击哪了,那个加active 类
    • activeClassName="atguigu"
  • 自封装 MyNavLink

    <MyNavLink to="/about" a={
          
          1} b={
          
          2}>About</MyNavLink>
    <MyNavLink to="/home">Home</MyNavLink>
    
    export default class MyNavLink extends Component {
          
          
        render() {
          
          
            console.log(this.props);
            // const {title} = this.props
            return (
                // <NavLink className="list-group-item" {...this.props}>{this.props.children}</NavLink>
                <NavLink className="list-group-item" {
          
          ...this.props}></NavLink>
            )
        }
    }
    
  • 解决资源丢失(3种)

    • HashRouter #后边的东西认为是前端东西,不走缓存

    • ./css/bootstrap.css  
      ---> /css/bootstrap.css
      ---> %PUBLIC_URL%/css/....
      
  • 路由的模糊与严格匹配

    • 模糊匹配

      <MyNavLink to="/home/a/b">Home</MyNavLink> // it could
      <MyNavLink to="/c/home/a/b">Home</MyNavLink> // wrong
      
    • 精准匹配

      {
              
              /* 注册路由,展示内容 严格匹配 */}
      <Route path="/about" component={
              
              About} />
      <Route exact={
              
              true} path="/home" component={
              
              Home} />
      
  • Redirect的使用

    重定向

    一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由

    <Switch>
        {
          
          /* 注册路由,展示内容 */}
        <Route path="/about" component={
          
          About} />
        <Route path="/home" component={
          
          Home} />
        <Redirect to="/about"></Redirect>
    </Switch>
    

5.4 嵌套路由使用

  • 注册子路由时要写上父路由的path值
  • 路由的匹配是按照注册路由的顺序进行的
<div>
    <h3>我是Home的内容</h3>
    <ul class="nav nav-tabs">
        <li>
            <MyNavLink to="/home/news">News</MyNavLink>
        </li>
        <li>
            <MyNavLink to="/home/message">Message</MyNavLink>
        </li>
    </ul>
    {
    
    /* 注册路由 */}
    <Switch>
        <Route path="/home/news" component={
    
    News}></Route>
        <Route path="/home/message" component={
    
    Message}></Route>
        <Redirect to="/home/news"></Redirect>
    </Switch>
</div>

5.5 向路由组件传递参数数据

  • 向路由组件传递params 参数

    路由链接:携带参数

    注册路由:声明接受

    接收参数:this.porps.match.params

    messageArr.map((msgObj) => {
          
          
        return (
            <li key={
          
          msgObj.id}>
                {
          
          /* 向路由组件传递params参数 */}
                <Link to={
          
          `/home/message/detail/${
            
            msgObj.id}/${
            
            msgObj.title}`}>{
          
          msgObj.title}</Link>
                &nbsp;&nbsp;
            </li>
        )
    })
    
    {
          
          /* 注册路由 */}
    <Route path="/home/message/detail/:id/:title" component={
          
          Detail} />
    
    // 接收
    const {
          
          id, title} = this.props.match.params;
    
  • 向路由组件传递search参数

    路由链接:携带参数

    注册路由:无需声明,正常注册即可

    接收参数:this.props.location.search

    querystring 库 : urlencoded 编码与 Json 转化

    import qs from 'querystring'
    
    let obj = {
          
          name:'tom', age:18}
    qs.stringfy(obj) // name=tom&age=18
    
    let str = 'name=tom&age=18'
    qs.parse(str) // {name:'tom', age:18}
    
    messageArr.map((msgObj) => {
          
          
        return (
            <li key={
          
          msgObj.id}>
                {
          
          /* 向路由组件传递params参数 */}
                <Link to={
          
          `/home/message/detail/?id=${
            
            msgObj.id}&title=${
            
            msgObj.title}`}>{
          
          msgObj.title}</Link>
                &nbsp;&nbsp;
            </li>
        )
    })
    
    {
          
          /* 注册路由  search 参数无需生命接受,正常注册路由即可 */}
    <Route path="/home/message/detail" component={
          
          Detail} />
    
    // 接收search参数
    const {
          
          search} = this.props.location
    const {
          
          id, title} = qs.parse(search.slice(1))
    
  • 向路由组件传递state参数

    路由链接:携带参数

    注册路由:无需声明

    接收参数:this.props.location.state

    ps:刷新也可以保留住参数

    messageArr.map((msgObj) => {
          
          
        return (
            <li key={
          
          msgObj.id}>
                {
          
          /* 向路由组件传递params参数 */}
                <Link to={
          
          {
          
          
                        pathname:'/home/message/detail',
                            state:{
          
          
                                id:msgObj.id,
                                title : msgObj.title
                            }
                    }} >{
          
          msgObj.title}</Link>
                &nbsp;&nbsp;
            </li>
        )
    })
    
    <Route path="/home/message/detail" component={
          
          Detail} />
        
    // 接收state参数
    const {
          
          id, title} = this.props.location.state || {
          
          }
    
    const findResult = data.find((detailObj)=>{
          
          
        return detailObj.id === id;
    }) || {
          
          }
    

5.6 多种路由跳转方式

  • push
  • replace

5.7 编程式路由导航

replaceShow = (id, title)=>{
    
    
    // replace跳转+携带params参数
  	this.props.history.replace(`/home/message/detail/${
      
      id}/${
      
      title}`)

    // replace跳转+携带search参数
    this.props.history.replace(`/home/message/detail/?id=${
      
      id}&title=${
      
      title}`)

    // push跳转+携带state参数
    this.props.history.replace(`/home/message/detail`, {
    
    id:id, title:title})
}

pushShow = (id, title)=>{
    
    
    // push跳转+携带params参数
    this.props.hsistory.push(`/home/message/detail/${
      
      id}/${
      
      title}`)

    // push跳转+携带search参数
    this.props.history.push(`/home/message/detail/?id=${
      
      id}&title=${
      
      title}`)

    // push跳转+携带state参数
    this.props.history.push(`/home/message/detail`, {
    
    id:id, title:title})
}

5.8 withRouter使用

import React, {
    
     Component } from 'react'
import {
    
    withRouter} from 'react-router-dom'

class Header extends Component {
    
    

    /* 
        只有路由组件才有history
        一般组件没有history
        withRouter 可以让一般组件用于路由组件的history
    */
    back = () => {
    
    
        this.props.history.goBack();
    }

    forward = () => {
    
    
        this.props.history.goForward();
    }

    go = () => {
    
    
        this.props.history.go(-2);
    }

    render() {
    
    
        // console.log('header组件收到的props是', this.props);
        return (
            <div>
                <h2>React Router Demo</h2>
                <button onClick={
    
    this.back}>回退</button>
                <button onClick={
    
    this.forward}>前进</button>
                <button onClick={
    
    this.go}>go</button>   
            </div>
        )
    }
}

/* 
    暴露withRouter的返回值
    给一般组件加工 history 等api
    withRouter的返回值是要给新组件
*/
export default withRouter(Header);

5.9 BrowserRouter与HashRouter

  1. 底层原理不同:
    • BrowserRouter使用的是H5的history API, 不兼容IE9及以下版本。
    • HashRouter使用的是URL的哈希值
  2. url表现形式不一样:
    • BrowserRouter的路径种没有#,例如:localhost:3000/demo/test
    • HashRouter的路径包含#,例如:localhost:3000/#/demo/test
  3. 刷新后对路由state参数的影响:
    • BrowserRouter没有任何影响,因为state保存在history对象中
    • HashRouter刷新后会导致路由state参数的丢失
  4. PS:HashRouter可以用于解决一些路径错误相关的问题。

猜你喜欢

转载自blog.csdn.net/mango660/article/details/119295207