【React】 第九部分 react 路由

【React】 第九部分 react 路由



9. react 路由

9.1 路由基本使用

下载react-router-dom : npm install --save react-router-dom@5

在原生中是依靠a标签实现跳转页面,而在react中是依靠路由链接进行切换组件

在使用路由链接的时候需要注意 : 最外层需要包裹BrowserRouter或者HashRouter,最后会说两个路由器的区别

因为整个引用只能归一个路由器管

import React, { Component } from 'react'
import Home from '../../pages/Home/Home'
import About from '../../pages/About/About'
import { Link, Route,BrowserRouter } from "react-router-dom"
export default class Header extends Component {
    render() {
        return (
            <div>
                <BrowserRouter>
                    <div className="row">
                        <div className="col-xs-offset-2 col-xs-8">
                            <div className="page-header"><h2>React Router Demo</h2></div>
                        </div>
                    </div>
                    <div className="row">
                        <div className="col-xs-2 col-xs-offset-2">
                            <div className="list-group">
                                {/* 使用路由链接,to表示的是要跳转的路径 */}
                                <Link className="list-group-item" to="/about">About</Link>
                                <Link className="list-group-item" to="/home">Home</Link>
                            </div>
                        </div>
                    </div>
                    <div className="col-xs-6">
                    {/* 
                        注册路由
                            path:表示匹配的路径
                            component:组件
                    */}
                        <Route path="/about" component={About} />
                        <Route path="/home" component={Home} />
                    </div>
                </BrowserRouter>
            </div>
        )
    }
}

9.2 一般组件和路由组件的区别

  1. 写法不同:

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

    • 一般组件:写在components文件夹下
    • 路由组件:写在pages文件夹下
  3. 接收到的props参数不同:

    • 一般组件:写组件标签的时候,传入什么,就接收到什么

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

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

9.3 NavLink组件的使用以及二次封装

NavLink是Link路由组件的升级版

作用:当该组件被触发的时候会给追加一个类名默认为active

activeClassName="xxx" 这个属性可以用来去修改默认类名

export default class Header extends Component {
    render() {
        return (
            <div>
                <BrowserRouter>
                    <div className="row">
                        <div className="col-xs-offset-2 col-xs-8">
                            <div className="page-header"><h2>React Router Demo</h2></div>
                        </div>
                    </div>
                    <div className="row">
                        <div className="col-xs-2 col-xs-offset-2">
                            <div className="list-group">
                                {/* 使用NavLink,to表示的是要跳转的路径 */}
                                <NavLink activeClassName='hidden' className="list-group-item" to="/about">About</NavLink>
                                <NavLink className="list-group-item" to="/home">Home</NavLink>
                            </div>
                        </div>
                    </div>
                    <div className="col-xs-6">
                        {/* 
                        注册路由
                            path:表示匹配的路径
                            component:组件
                    */}
                        <div className="panel">
                            <div className="panel-body">
                                <Route path="/about" component={About}></Route>
                                <Route path="/home" component={Home}></Route>
                            </div>
                        </div>
                    </div>
                </BrowserRouter>
            </div>
        )
    }
}

根据需要对NavLink进行二次封装

import React, { Component } from 'react'
import {NavLink} from "react-router-dom"
export default class MyNavLink extends Component {
  render() {
    return (
        // 举个例子有公共的高亮样式和公共的类,其他通过props传入
        /*
            知识点:
                通过props,标签属性传入key:value形式,props就能够接收到指定的key:value
                那么标签体,props其实也是可以接收到,只不过它给我们固定的一个key,名为children 
         */
       <NavLink activeClassName='active' className="list-group-item" {...this.props}>{this.props.children}</NavLink>
    )
  }
}

// 二者可以对比一下
<NavLink activeClassName='active' className="list-group-item" to="/about">About</NavLink>
<NavLink activeClassName='active' className="list-group-item" to="/about">About</NavLink>

<MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/home">Home</MyNavLink>

9.4 Switch组件的使用

作用:Switch能够提高匹配路由的效率

那么被Switch组件包裹后,只要匹配到第一个对应的路由那么就会停止匹配

<Switch>
  	<Route path="/about" component={About}></Route>
	<Route path="/a" component={A}></Route>
	<Route path="/B" component={B}></Route>
	<Route path="/about" component={About}></Route>
</Switch>

9.5 解决多级路径刷新页面样式丢失的问题

方法一:

​ 在public/index.html中引入样式的时候不写.//

方法二:

​ 在public/index.html中引入样式的时候不写./%PUBLIC_URL%

方法三:

​ 使用HashRouter

9.6 Redirect 组件的使用

作用:重定向路由,当没有匹配到任何的路由时,跳转到Redirect所指定的路由

一般写在注册路由的最下方

<Switch>
  <Route path="/about" component={About}></Route>
	<Route path="/home" component={Home}></Route>
	<Redirect to="/about" />
</Switch>

9.7 嵌套路由

嵌套路由需要注意的点:

  1. 在注册子路由的时候需要在前面加上父路由的path值
  2. 路由的匹配是按照注册路由的顺序进行的
  3. 简单来说,父路由先有才会有子路由
export default class Home extends Component {
    render() {
        return (
            <div>
                <h3>我是Home的内容</h3>
                <div>
                    <ul className="nav nav-tabs">
                        <li>
                            <MyNavLink to="/home/news">News</MyNavLink>
                        </li>
                        <li>
                            <MyNavLink to="/home/message">Message</MyNavLink>
                        </li>
                    </ul>            
                </div>
                {/* 注册子路由 */}
                <Switch>
                    <Route path="/home/news" component={News}/>
                    <Route path="/home/message" component={Message}/>
                    <Redirect to="/home/news"/>
                </Switch>
            </div>
        )
    }
}

9.8 向路由组件传递params参数

步骤:

  1. 在路径中携带好params参数

  2. 通过 :xxx 声明params参数

  3. 传入的params参数,可以用this.props.match.params进行接收
    在这里插入图片描述

export default class Message extends Component {
    state = {
        messageList:[
            {id:1,title:'消息1'},
            {id:2,title:'消息2'},
            {id:3,title:'消息3'},
        ]
    }
    render() {
        return (
            <ul>
                {
                    this.state.messageList.map((item)=>{
                        return (
                            <li key={item.id}>
                                {/* 传params参数 */}
                                <Link to={`/home/message/detail/${item.id}/${item.title}`}>{item.title}</Link>
                            </li>
                        )
                    })
                }
                {/* 
                    注册路由
                        在这里需要声明params参数
                        :xx 相当于占位
                 */}
                <Route path="/home/message/detail/:id/:title" component={Detail}/>
            </ul>
        )
    }
}

9.9 向路由组件传递search参数

步骤:

  1. 在路径中携带好search参数

  2. 传search参数,其实就是query参数 以 ? 开头 & 进行串联, 形式是key:value

  3. 需要注意的是seach参数,react没有像params参数那样帮我们整理好,接收的方式this.props.location.search

    获取到的数据类似?id=2&title=消息2,所以可以自己写一个函数去整理得到的参数

在这里插入图片描述

export default class Message extends Component {
    state = {
        messageList:[
            {id:1,title:'消息1'},
            {id:2,title:'消息2'},
            {id:3,title:'消息3'},
        ]
    }
    render() {
        return (
            <ul>
                {
                    this.state.messageList.map((item)=>{
                        return (
                            <li key={item.id}>
                                {/* 
                                    传search参数,其实就是query参数 
                                    以 ? 开头 & 进行串联
                                */}
                                <Link to={`/home/message/detail?id=${item.id}&title=${item.title}`}>{item.title}</Link>
                            </li>
                        )
                    })
                }
                {/* 
                    注册路由:
                        在这里不需要声明search参数
                 */}
                <Route path="/home/message/detail" component={Detail}/>
            </ul>
        )
    }
}

9.10 向路由组件传递state参数

步骤:

  1. 在路径中携带好state参数,以对象的形式

  2. 和上述两个参数不同在于:传入的参数不会展示在地址栏

  3. 刷新页面也不会丢失

在这里插入图片描述

import React, { Component } from 'react'
import {Link, Route} from "react-router-dom"
import Detail from './Detail/Detail'
export default class Message extends Component {
    state = {
        messageList:[
            {id:1,title:'消息1'},
            {id:2,title:'消息2'},
            {id:3,title:'消息3'},
        ]
    }
    render() {
        return (
            <ul>
                {
                    this.state.messageList.map((item)=>{
                        return (
                            <li key={item.id}>
                                {/*
                                    传state参数 ,以对象的形式
                                 */}
                                <Link to={{pathname:'/home/message/detail',state:{id:item.id,title:item.title}}}>{item.title}</Link>
                            </li>
                        )
                    })
                }
                {/* 
                    注册路由:
                        在这里不需要声明state参数
                 */}
                <Route path="/home/message/detail" component={Detail}/>
            </ul>
        )
    }
}

9.11 push和replace

push模式 :浏览器可以进行回退(默认开启push模式)

replace模式: 不能进行回退

<Link replace to={`/home/message/detail/${item.id}/${item.title}`}>{item.title}</Link>

9.12 编程式路由导航

编程式路由导航的使用方法基本差不多

说白了就是通过去调用this.props.history下的API对路由跳转进行控制

 handlePush = (id,title) =>{
        /* 
            可以参两个参数
                - 第一个参数是路径
                - 第二个参数是state
        */
        // push跳转携带params参数    
        this.props.history.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,title})
    }

    handleReplace = (id,title) =>{
         /* 
            可以参两个参数
                - 第一个参数是路径
                - 第二个参数是state
        */
        // replace跳转携带params参数    
        this.props.history.replace(`/home/message/detail/${id}/${title}`)

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

        // replace跳转携带state参数
        this.props.history.replace('/home/message/detail',{id,title})
    }
    
    handleGo = () =>{
      	// 可以传入参数,正数表示向前跳转2次
      	// 可以传入参数,负数表示向后跳转2次
        this.props.history.go(2)
      	this.props.history.go(-2)
    }

    handleGoBack = () =>{
      	// 后退一次
        this.props.history.goBack()
    }

    handleGoForward = () =>{
      	// 前进一次
        this.props.history.goForward()     
    }

9.13 withRouter

作用 : 可以加工一般组件,让一般组件拥有路由组件特有的API

在9.2有述说一般组件和路由组件的不同之处,其中最主要的区别就是接收到的props参数不同

import {withRouter} from 'react-router-dom'
class Header extends Component {
    render() {
        console.log(this.props);
        return (
            <div>
            </div>
        )
    }
}

export default withRouter(Header)

9.14 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可以用于解决一些路径错误相关的问题


总结

以上就是今天要讲的内容,希望对大家有所帮助!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值