十五、react 路由

中文文档:React Router: Declarative Routing for React.js

英文:Declarative routing for React apps at any scale | React Router

1. 相关理解

1.1. SPA的理解

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

补充:react的路由是用浏览器BOM的history实现,实现路径的前进后退替换。

history有两种工作模式:

第一种模式是:直接使用H5推出的history身上的API

第二种模式是:Hash值(锚点),就像锚点跳转

前端路由原理

一般借助 history.js管理

https://cdn.bootcss.com/history/4.7.2/history.js

1、前端路由主要依靠BOM的 api   history(浏览器的历史记录) 不会引发页面刷新
2、let history = History.createBrowserHistory() //方法一,直接使用H5推出的history身上的API 创建 history对象
3、let history = History.createHashHistory() //方法二,hash值(锚点)
4、history.listen 监听路径变化
5、history.push 在浏览历史记录添加一条数据  点击前进后退一条历史记录
6、浏览器的历史记录是栈结构 (历史记录是进栈出栈) 
7、history.replace(path) 替换上一条历史记录
8、history.goBack()后退  history.goForward()前进
 

	
	

1.2. 路由的理解

1.2.1 什么是路由?

  1. 一个路由就是一个映射关系(key: value)
  2. key为路径, value可能是functioncomponent

1.2.2 路由分类

1. 后端路由

  1. 理解: valuefunction, 用来处理客户端提交的请求。
  2. 注册路由: router.get(path, function(req, res))
  3. 工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据

2. 前端路由

  1. 浏览器端路由,value是component,用于展示页面内容。
  2. 注册路由: 
  3. 工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件

1.3. react-router-dom 的理解

  1. React的一个插件库。
  2. 专门用来实现一个SPA应用。
  3. 基于React的项目基本都会用到此库。

你所安装的库并不是react-router,因为react-router这个库有三种实现,给三种平台去用,第一种是web网页开发人员,第二种是native,是给写react native的人用的,第三种是any,在哪种都能用。我们学的是第一种web用的react-router-dom。

十五、react 路由_第1张图片

 

2. react-router-dom相关API

2.1. 内置组件

2.2. 其它

  1. history对象
  2. match对象
  3. withRouter函数

3. 基本路由使用

3.1. 效果

十五、react 路由_第2张图片

3.2. 准备

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

在这里插入图片描述

 2、引入bootstrap.css: 

3.3 路由的基本使用

1、明确好界面中的导航区、展示区
2、导航区的a标签改为Link标签
Demo
3、展示区写Route标签进行路径的匹配

4、的最外侧包裹了一个(history对象)或(hash值(#号后面的值)的切换,不会发给服务器)

3.4 实现

index.js

这里用一个标签将整个App包起来,保证使用的是同一个路由器

//引入react核心库
import React from 'react'
//引入ReactDOM
import ReactDOM from 'react-dom'
//
import {BrowserRouter} from 'react-router-dom'
//import {HashRouter} from 'react-router-dom'

//引入App
import App from './App'




//把BrowserRouter换成HashRouter后链接就会变成井号的形式
/*
例如:
1、BrowserRouter
链接:localhost:3000/about

2、HashRouter
链接:localhost:3000/#/about

*/

ReactDOM.render(
	
		
	,
	document.getElementById('root')
)

App.jsx

import React, { Component } from 'react'
import { Link,Route } from 'react-router-dom'
import Home from './Home'
import About from './About'

export default class App extends Component {
  render() {
    return (
      

React Router Demo

{/* 原生html中,靠跳转不同的页面 */} {/* About Home */} {/* 在React中靠路由链接实现切换组件--编写路由链接 */} About Home
{/* 注册路由 */}
) } }

components/About/index.jsx

import React,{Component} from "react";

export default class About extends Component {
    render(){
        return (
        

我是About的内容

) } }

components/Home/index.jsx

import React,{Component} from "react";

export default class Home extends Component {
 console.log(this.props)
    render(){
        return (
        

我是Home的内容

) } }

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

1、写法不同:
一般组件:
路由组件:
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"

十五、react 路由_第3张图片

 

十五、react 路由_第4张图片

 

 

3.6 NavLink与封装NavLink

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

Home

可以自己封装一个NavLink【一般组件】

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

export default class MyNavLink extends Component {
  render() {
	// console.log(this.props);
	return (
	  
	)
  }
}

标签体内容是特殊的标签属性通过this.props.children可以获取标签体内容
使用

About
Home

3.7 Switch的使用

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

  
  
  

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

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

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

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

  1. 默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
  2. 开启严格匹配:
  3. 严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由

3.10 Redirect的使用 【重定向】

  1. 一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
  2. 具体编码:

	
	
	

4. 嵌套路由使用

4.1 效果

十五、react 路由_第5张图片

4.2 注意

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

4.3 实现

Home/index.jsx

import React, { Component } from 'react'
import { Route, NavLink,Redirect,Switch } from 'react-router-dom'
import News from './News'
import Message from './Message'

export default class Home extends Component {
  render() {
    return (
      

我是Home的内容

  • News
  • Message
) } }

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

5.1 效果

十五、react 路由_第6张图片

5.2 具体方法

方法1. params参数

1、路由链接(携带参数):详情
2、注册路由(声明接收):
3、接收参数:this.props.match.params
Message/index.jsx

import React, { Component } from 'react'
import { Link, Route } from 'react-router-dom';
import Detail from './Detail';

export default class Message extends Component {
  state = {
    messageArr: [
      { id: '01', title: '消息1' },
      { id: '02', title: '消息2' },
      { id: '03', title: '消息3' },
    ]
  }
  render() {
    const { messageArr } = this.state;
    return (
      
    { messageArr.map((msgObj) => { return (
  • {/* 向路由组件传递params参数 */} {msgObj.title}
  • ) }) }

{/* 声明接收params参数 */}
) } }

Detail/index.jsx

十五、react 路由_第7张图片

import React, { Component } from 'react'

export default class Detail extends Component {
  state = {
    detailData : [
      { id: '01', content: '你好啊' },
      { id: '02', content: '还不错鸭' },
      { id: '03', content: '显示我吧' }
    ]
  }
  render() {
    console.log(this.props)
    // 接收params参数
    const { id, title } = this.props.match.params
    const findResult= this.state.detailData.find((dataObj) => {
      return dataObj.id === id
    })
    return (
      
  • ID: {id }
  • Title: {title }
  • Content: { findResult.content}
) } }

方法2. search参数

1、路由链接(携带参数):详情
2、注册路由(无需声明,正常注册即可):
3、接收参数:this.props.location.search
4、备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
 

qs库 (querystring)

qs.stringify 转为urlencoded编码字符串 name=tom&age=18

qs.parse 转为对象

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}
	{/* 向路由组件传递search参数 */}
{msgObj.title}
{/* search参数无需声明接收,正常注册路由即可 */}

-----------------------------------
 
import qs from 'querystring'
const DetailData = [
	{id:'01',content:'你好,中国'},
	{id:'02',content:'你好,世界'},
	{id:'03',content:'你好,未来的自己'}
]
export default class Detail extends Component {
	render() {
		console.log(this.props);
 
		// 接收search参数
		const {search} = this.props.location
		const {id,title} = qs.parse(search.slice(1))
 
		const findResult = DetailData.find((detailObj)=>{
			return detailObj.id === id
		})
		return (
			
  • ID:{id}
  • TITLE:{title}
  • CONTENT:{findResult.content}
) } }

方法3. state参数

1、路由链接(携带参数):详情
2、注册路由(无需声明,正常注册即可):
3、接收参数:this.props.location.state
4、备注:刷新也可以保留住参数【history对象记录着在】

代码

Message/index.jsx

export default class Message extends Component {
  render() {
    const {messageArr} = this.state
    return (
      
    { messageArr.map((msgObj)=>{ return (
  • {/* 向路由组件传递params参数 */} {/* {msgObj.title} */} {/* 向路由组件传递search参数 */} {/* {msgObj.title} */} {/* 向路由组件传递state参数 */} {msgObj.title}
  • ) }) }

{/* 声明接收params参数 */} {/* */} {/* search参数无需声明接收,正常注册路由即可 */} {/* */} {/* state参数无需声明接收,正常注册路由即可 */}
) } }

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 (
      
  • ID:{id}
  • TITLE:{title}
  • CONTENT:{findResult.content}
) } }

6. 多种路由跳转方式

6.1 编程式路由导航

借助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.2 withRouter的使用

export default withRouter(Header)

withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
withRouter的返回值是一个新组件

7. 注意

BrowserRouter与HashRouter的区别

1、底层原理不一样:
BrowserRouter使用的是H5的history 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可以用于解决一些路径错误相关的问题。
 

https://blog.csdn.net/weixin_44972008/article/details/117856718

【React】SPA - 路由机制 - react-router-dom - 基本路由 - 嵌套路由 - 传递参数 - 路由跳转_YK菌的博客-CSDN博客

React路由_前端 贾公子的博客-CSDN博客

印记中文,有好多前端的中文文档https://docschina.org/

你可能感兴趣的:(reactjs,react.js,前端,javascript)