SPA
)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()前进
key: value
)key
为路径, value
可能是function
或component
1. 后端路由
value
是function
, 用来处理客户端提交的请求。router.get(path, function(req, res))
node
接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据2. 前端路由
component
,用于展示页面内容。
path
变为/test
时, 当前路由组件就会变为Test
组件React
的一个插件库。React
的项目基本都会用到此库。你所安装的库并不是react-router,因为react-router这个库有三种实现,给三种平台去用,第一种是web网页开发人员,第二种是native,是给写react native的人用的,第三种是any,在哪种都能用。我们学的是第一种web用的react-router-dom。
history
对象match
对象withRouter
函数npm install react-router-dom
2、引入bootstrap.css:
1、明确好界面中的导航区、展示区
2、导航区的a标签改为Link标签
Demo
3、展示区写Route标签进行路径的匹配
4、
这里用一个标签将整个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')
)
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
{/* 注册路由 */}
)
}
}
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的内容
)
}
}
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"
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
这样只要匹配到了第一个就不会再往下匹配了
./
写 /
(常用)【绝对路径】./
写 %PUBLIC_URL%
(常用)HashRouter
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
)
}
}
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
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}
)
}
}
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}
)
}
}
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}
)
}
}
借助this.prosp.history对象上的API对操作路由跳转、前进、后退
- this.prosp.history.push()
- this.prosp.history.replace()
- this.prosp.history.goBack()
- this.prosp.history.goForward()
- this.prosp.history.go()
export default withRouter(Header)
withRouter
可以加工一般组件,让一般组件具备路由组件所特有的APIwithRouter
的返回值是一个新组件
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/