第五章 React 路由
五、向路由组件传递参数数据
1. 效果
2. 代码 - 传递 params 参数
2.1 Message
javascript
复制代码
/* src/pages/Home/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 (
<div>
<ul>
{
messageArr.map((msgObj)=>{
return (
<li key={msgObj.id}>
{/* 向路由组件传递params参数 */}
<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
</li>
)
})
}
</ul>
<hr />
{/* 声明接收params参数 */}
<Route path="/home/message/detail/:id/:title" component={Detail}/>
</div>
);
}
}
2.2 Detail
javascript
复制代码
/* src/pages/Home/Message/Detail/index.jsx */
import React, { Component } from 'react'
const Detaildata = [
{id:'01', content:'你好,中国'},
{id:'02', content:'你好,小帽学堂'},
{id:'03', content:'你好,未来的自己'}
]
export default class Detail extends Component {
render() {
//接收params参数
const {id, title} = this.props.match.params
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>
)
}
}
3. 代码 - 传递 search 参数
3.1 Message
javascript
复制代码
/* src/pages/Home/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 (
<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>
</li>
)
})
}
</ul>
<hr />
{/* 声明接收params参数 */}
{/* <Route path="/home/message/detail/:id/:title" component={Detail}/> */}
{/* search参数无需声明接收,正常注册路由即可 */}
<Route path="/home/message/detail" component={Detail}/>
</div>
);
}
}
3.2 Detail
javascript
复制代码
/* src/pages/Home/Message/Detail/index.jsx */
import React, { Component } from 'react'
import qs from 'querystring'
const Detaildata = [
{id:'01', content:'你好,中国'},
{id:'02', content:'你好,小帽学堂'},
{id:'03', content:'你好,未来的自己'}
]
export default class Detail extends Component {
render() {
// 接收params参数
// const {id, title} = this.props.match.params
// 接收search参数
const {search} = this.props.location
const {id, title} = qs.parse(search.slice(1))
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>
)
}
}
4. 代码 - 传递 state 参数
4.1 Message
javascript
复制代码
/* src/pages/Home/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 (
<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>
);
}
}
4.2 Detail
javascript
复制代码
/* src/pages/Home/Message/Detail/index.jsx */
import React, { Component } from 'react'
// import qs from 'querystring'
const Detaildata = [
{id:'01', content:'你好,中国'},
{id:'02', content:'你好,小帽学堂'},
{id:'03', content:'你好,未来的自己'}
]
export default class Detail extends Component {
render() {
// 接收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>
)
}
}
5. 总结
bash
复制代码
1.params参数
路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
接收参数:this.props.match.params
2.search参数
路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.search
备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
3.state参数
路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.state
备注:刷新也可以保留住参数
6. 代码 - push 与 replace 模式
Message
javascript
复制代码
/* src/pages/Home/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 (
<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 replace 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>
);
}
}
六、多种路由跳转方式
1. 效果
2. 代码 - 跳转 + 携带 params 参数
2.1 Message
javascript
复制代码
/* src/pages/Home/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" },
],
};
pushShow = (id, title) => {
//push跳转+携带params参数
this.props.history.push(`/home/message/detail/${id}/${title}`)
}
replaceShow = (id, title) => {
//replace跳转+携带params参数
this.props.history.replace(`/home/message/detail/${id}/${title}`)
}
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>
<button onClick={()=>this.pushShow(msgObj.id, msgObj.title)}>push查看</button>
<button onClick={()=>this.replaceShow(msgObj.id, msgObj.title)}>replace查看</button>
</li>
);
})}
</ul>
<hr />
{/* 声明接收params参数 */}
<Route path="/home/message/detail/:id/:title" component={Detail} />
</div>
);
}
}
2.2 Detail
javascript
复制代码
/* src/pages/Home/Message/Detail/index.jsx */
import React, { Component } from 'react'
// import qs from 'querystring'
const Detaildata = [
{id:'01', content:'你好,中国'},
{id:'02', content:'你好,小帽学堂'},
{id:'03', content:'你好,未来的自己'}
]
export default class Detail extends Component {
render() {
// 接收params参数
const {id, title} = this.props.match.params
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>
)
}
}
3. 代码 - 跳转 + 携带 state 参数
3.1 Message
javascript
复制代码
/* src/pages/Home/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" },
],
};
pushShow = (id, title) => {
//push跳转+携带state参数
this.props.history.push(`/home/message/detail`, {id,title})
}
replaceShow = (id, title) => {
//replace跳转+携带state参数
this.props.history.replace(`/home/message/detail`, {id,title})
}
render() {
const { messageArr } = this.state;
return (
<div>
<ul>
{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>
<button onClick={()=>this.pushShow(msgObj.id, msgObj.title)}>push查看</button>
<button onClick={()=>this.replaceShow(msgObj.id, msgObj.title)}>replace查看</button>
</li>
);
})}
</ul>
<hr />
{/* 声明接收state参数 */}
<Route path="/home/message/detail" component={Detail} />
</div>
);
}
}
3.2 Detail
javascript
复制代码
/* src/pages/Home/Message/Detail/index.jsx */
import React, { Component } from 'react'
const Detaildata = [
{id:'01', content:'你好,中国'},
{id:'02', content:'你好,小帽学堂'},
{id:'03', content:'你好,未来的自己'}
]
export default class Detail extends Component {
render() {
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>
)
}
}
4. 代码 - 前进后退
javascript
复制代码
/* src/pages/Home/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" },
],
};
pushShow = (id, title) => {
//push跳转+携带state参数
this.props.history.push(`/home/message/detail`, { id, title });
};
replaceShow = (id, title) => {
//replace跳转+携带state参数
this.props.history.replace(`/home/message/detail`, { id, title });
};
back = () => {
this.props.history.goBack();
};
forward = () => {
this.props.history.goForward();
};
go = () => {
this.props.history.go(-2);
};
render() {
const { messageArr } = this.state;
return (
<div>
<ul>
{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>
<button onClick={() => this.pushShow(msgObj.id, msgObj.title)}>
push查看
</button>
<button
onClick={() => this.replaceShow(msgObj.id, msgObj.title)}
>
replace查看
</button>
</li>
);
})}
</ul>
<hr />
{/* 声明接收state参数 */}
<Route path="/home/message/detail" component={Detail} />
<button onClick={this.back}>回退</button>
<button onClick={this.forward}>前进</button>
<button onClick={this.go}>go</button>
</div>
);
}
}
5. 总结
bash
复制代码
借助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. withRouter 的使用
javascript
复制代码
/* src/components/Header/index.jsx */
import React, { Component } from 'react'
import {withRouter} from 'react-router-dom'
class Header extends Component {
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 className="page-header">
<h2>React Router Demo</h2>
<button onClick={this.back}>回退</button>
<button onClick={this.forward}>前进</button>
<button onClick={this.go}>go</button>
</div>
)
}
}
export default withRouter(Header)
//withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
//withRouter的返回值是一个新组件
七、BrowserRouter 与 HashRouter 的区别
bash
复制代码
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可以用于解决一些路径错误相关的问题。