[react] 路由

1. 相关理解

1.1. SPA的理解

单页Web应用(single page web application,SPA)
整个应用只有一个完整的页面。
点击页面中的链接不会刷新页面,只会做页面的局部更新。
数据都需要通过ajax请求获取, 并在前端异步展现。

1.2. 路由的理解

1.2.1 什么是路由?

一个路由就是一个映射关系(key: value)
key为路径, value可能是function或component

1.2.2 路由分类

1. 后端路由

理解: valuefunction, 用来处理客户端提交的请求。

注册路由:router.get(path, function(req, res))

工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
在这里插入图片描述
2. 前端路由
浏览器端路由,valuecomponent,用于展示页面内容。

注册路由: <Route path="/test" component={Test}>
工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件

路由原理history

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. react-router-dom相关API

2.1. 内置组件

<BrowserRouter>
<HashRouter>
<Route>
<Redirect>
<Link>
<NavLink>
<Switch>

2.2. 其它

history对象
match对象
withRouter函数

3. 基本路由使用

3.1. 效果

在这里插入图片描述

3.2. 准备

下载react-router-dom:
npm install react-router-dom

引入bootstrap.css:
<link rel="stylesheet" href="/css/bootstrap.css">

3.3 路由的基本使用

  1. 明确好界面中的导航区、展示区
  2. 导航区的a标签改为Link标签
    <Link to="/xxxxx">Demo</Link>
  3. 展示区写Route标签进行路径的匹配
    <Route path='/xxxx' component={Demo}/>
  4. <App>的最外侧包裹了一个<BrowserRouter><HashRouter>

3.4 实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.5 路由组件与一般组件的区别

写法不同:
一般组件:<Demo/>
路由组件:<Route path="/demo" component={Demo}/>
存放位置不同:
一般组件:components
路由组件:pages
接收到的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"

3.6 NavLink与封装NavLink

NavLink可以实现路由链接的高亮,通过activeClassName属性指定样式名,默认是"active"

<NavLink activeClassName="demo" className="list-group-item" to="/home">Home</NavLink>

可以自己封装一个NavLink【一般组件】
标签体内容是特殊的标签属性,通过this.props.children可以获取标签体内容

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

export default class MyNavLink extends Component {
  render() {
	// console.log(this.props);
	return (
	  <NavLik activeClassName="demo" className="list-group-item" {...this.props} />
	)
  }
}

在这里插入图片描述

在这里插入图片描述

this.props等于{to:’/about’,a:1,b:2,c:3,children:“About”}
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.7 Switch的使用

通常情况下,path和component是一一对应的关系。
Switch可以提高路由匹配效率(单一匹配)。

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

这样只要匹配到了第一个就不会再往下匹配了

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

  1. public/index.html 中 引入样式时不写.//(常用)【绝对路径】

在这里插入图片描述
2. public/index.html 中 引入样式时不写./%PUBLIC_URL%(常用)
在这里插入图片描述
3. 使用HashRouter

在这里插入图片描述

3.9 路由的严格匹配与模糊匹配

  1. 默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
    在这里插入图片描述

  2. 开启严格匹配:<Route exact={true} path="/about" component={About}/>
    在这里插入图片描述

  3. 严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由

3.10 Redirect的使用 【重定向】

  1. 一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
  2. 具体编码:
<Switch>
	<Route path="/about" component={About}/>
	<Route path="/home" component={Home}/>
	<Redirect to="/about"/>
</Switch>

4. 嵌套路由使用

4.1 效果

在这里插入图片描述
在这里插入图片描述

4.2 注意

  1. 注册子路由时要写上父路由的path值
  2. 路由的匹配是按照注册路由的顺序进行的

4.3 实现

在这里插入图片描述

src\index.js
在这里插入图片描述
APP.js
在这里插入图片描述

src\components\MyNavLink\index.jsx
在这里插入图片描述
src\pages\About\index.jsx
在这里插入图片描述

src\pages\Home\index.jsx
在这里插入图片描述

src\pages\Home\News\index.jsx
在这里插入图片描述
src\pages\Home\Message\index.jsx
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

5. 向路由组件传递参数数据

5.1 效果

在这里插入图片描述

在这里插入图片描述

5.2 具体方法

方法1. params参数
  1. 路由链接(携带参数):
    <Link to='/demo/test/tom/18'}>详情</Link>
  2. 注册路由(声明接收):
    <Route path="/demo/test/:name/:age" component={Test}/>
  3. 接收参数:this.props.match.params

在这里插入图片描述

在这里插入图片描述

src/index.js
在这里插入图片描述
src/App.jsx
在这里插入图片描述

src\pages\Home\index.jsx
在这里插入图片描述
src\pages\Home\Message\index.jsx
在这里插入图片描述

src\pages\Home\Message\Detail\index.jsx
在这里插入图片描述
在这里插入图片描述

方法2. search参数
  1. 路由链接(携带参数):
    <Link to='/demo/test?name=tom&age=18'}>详情</Link>
  2. 注册路由(无需声明,正常注册即可):
    <Route path="/demo/test" component={Test}/>
  3. 接收参数:this.props.location.search

备注:获取到的searchurlencoded编码字符串,需要借助querystring解析

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

import qs from 'querystring'
let obj = {name:'tom', age:18}
console.log(qs.stringify(obj)) // name=tom&age=18

let str = 'carName=Benz&price=199'
console.log(qs.parse(str)) // {carName: 'Benz', price: 199}

方法3. state参数
  1. 路由链接(携带参数):
<Link to={{ pathname:'/demo/test', state:{name:'tom',age:18} }}>详情</Link>
  1. 注册路由(无需声明,正常注册即可):
    <Route path="/demo/test" component={Test}/>
  2. 接收参数:this.props.location.state
    备注:刷新也可以保留住参数【history对象记录着在】

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

代码

Message/index.jsx

export default class Message extends Component {
  render() {
    const {messageArr} = this.state
    return (
      <div>
        <ul>
          {
            messageArr.map((msgObj)=>{
              return (
                <li key={msgObj.id}>

                  {/* 向路由组件传递params参数 */}
                  {/* <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link> */}

                  {/* 向路由组件传递search参数 */}
                  {/* <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link> */}

                  {/* 向路由组件传递state参数 */}
                  <Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link>

                </li>
              )
            })
          }
        </ul>
        <hr/>
        {/* 声明接收params参数 */}
        {/* <Route path="/home/message/detail/:id/:title" component={Detail}/> */}

        {/* search参数无需声明接收,正常注册路由即可 */}
        {/* <Route path="/home/message/detail" component={Detail}/> */}

        {/* state参数无需声明接收,正常注册路由即可 */}
        <Route path="/home/message/detail" component={Detail}/>
      </div>
    )
  }
}

Detail/index.jsx

import React, { Component } from 'react'
// import qs from 'querystring'

export default class Detail extends Component {
  render() {
    console.log(this.props);

    // 接收params参数
    // const {id,title} = this.props.match.params 

    // 接收search参数
    // const {search} = this.props.location
    // const {id,title} = qs.parse(search.slice(1))

    // 接收state参数
    const {id,title} = this.props.location.state || {}

    const findResult = DetailData.find((detailObj)=>{
      return detailObj.id === id
    }) || {}
    return (
      <ul>
        <li>ID:{id}</li>
        <li>TITLE:{title}</li>
        <li>CONTENT:{findResult.content}</li>
      </ul>
    )
  }
}

6. 多种路由跳转方式

6.1 push与replace模式

默认就是Pushs模式
开启repalce模式
在这里插入图片描述

6.2 编程式路由导航

借助this.prosp.history对象上的API对操作路由跳转、前进、后退

  • this.prosp.history.push()
  • this.prosp.history.replace()
  • this.prosp.history.goBack()
  • this.prosp.history.goForward()
  • this.prosp.history.go()
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

6.3 withRouter的使用

export default withRouter(Header)

withRouter可以加工一般组件,让一般组件具备路由组件所特有的API

withRouter的返回值是一个新组件

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

7. 注意

BrowserRouter与HashRouter的区别

  1. 底层原理不一样:
    BrowserRouter使用的是H5history API,不兼容IE9及以下版本。
    HashRouter使用的是URL的哈希值。

  2. path表现形式不一样
    BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
    HashRouter的路径包含#,例如:localhost:3000/#/demo/test

  3. 刷新后对路由state参数的影响
    (1) BrowserRouter没有任何影响,因为state保存在history对象中。
    (2)HashRouter刷新后会导致路由state参数的丢失!!!

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

在这里插入图片描述

在这里插入图片描述



参考:
【React】SPA - 路由机制 - react-router-dom - 基本路由 - 嵌套路由 - 传递参数 - 路由跳转

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值