1 嵌套路由
1.1 使用
示例效果如下图1.1-1所示:
该示例代码其他部分和上一篇相同,这里主要讲解下嵌套路由的使用。
分析:home组件中嵌套了News和Message两个路由组件。
-
创建News组件
-
在原项目结构Home文件夹下创建News/index.jsx
-
源代码1.1-1如下所示
import React, { Component } from 'react' export default class News extends Component { render() { return ( <ul> <li>news001</li> <li>news002</li> <li>news003</li> </ul> ) } }
-
-
创建Message组件
-
Home文件夹下创建Message/index.jsx
-
源代码1.1-2如下图所示
import React, { Component } from 'react' export default class Message extends Component { render() { return ( <div> <ul> <li> <a href="/message1">message001</a> </li> <li> <a href="/message2">message002</a> </li> <li> <a href="/message/3">message003</a> </li> </ul> </div> ) } }
-
-
Home/jsx添加导航链接和注册路由
-
源代码1.1-3如下所示:
import React, { Component } from 'react' import { Route, Switch, Redirect } from 'react-router-dom'; import MyNavLink from '../../components/MyNavLink' import Message from './Message'; import News from './News' 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> ) } }
-
启动项目,完成嵌套路由的使用。
- 分析路由匹配原理
- 首先react完成App.jsx中路由注册
- 当点击News时,对应路径"/home/news"开始按照路由注册顺序开始匹配。
- 优先模糊匹配"/home",展示Home组件。
- 继续匹配Home组件中路径"/home/news",展示News组件。
1.2 总结
- 注册路由时要写上父路由的path值;
- 路由匹配是按照注册路由的顺序进行的。
2 路由传参
2.1 示例准备
示例效果,点击消息,展示对应的消息内容,如下图2.1-1所示:
示例其他代码同上,这里只写对应的消息部分。
-
简单分析
- 当前为二级路由下导航链接,点击链接,展示消息详情,即为三级路由。
- 消息详情结构一致,封装为路由组件Detail。
- Message组件下消息结构一样,内容不同,在state中写数据,遍历动态生成。
-
Detail组件代码2.1-1如下所示:
import React, { Component } from 'react' export default class Detail extends Component { render() { return ( <ul> <li>ID:xxx</li> <li>TITLE:xxx</li> <li>CONTENT:xxx</li> </ul> ) } }
-
Messge组件代码2.1-2如下所示:
import React, { Component } from 'react' import { Link, Route } from 'react-router-dom' import Detail from './Detail' export default class Message extends Component { state = { messArr : [ { id: '01', title: '消息1' }, { id: '02', title: '消息2' }, { id: '03', title: '消息3' }, ] } render() { const { messArr } = this.state return ( <div> <ul> { messArr.map((msg) => { return ( <li key={msg.id}> <Link to="/home/message/detail">{msg.title}</Link> </li> ) }) } </ul> <hr /> <Route path="/home/message/detail" component={Detail}></Route> </div> ) } }
如果想要实现点击不同消息链接,展示不同的消息内容,需要通过路由传递参数。下面我们详细讲解三种路由传参方式,并做总结和比较。
2.1 传递params参数
-
第一步:路由链接向路由组件传递params参数
{/* 格式:/} <Link to="/path1/path2/.../pathn/参数1/参数2/.../参数n"></Link> {/* 示例:/} {/* 向路由组件传递params参数 */} <Link to={`/home/message/detail/${msg.id}/${msg.title}`}>{msg.title}</Link>
-
第二步:路由组件声明接收params参数
{/* 格式 */} <Route path="/path1/path2/.../pathn/:参数1/:参数2/.../:参数n" component={组件}></Route> {/* 示例 */} {/* 声明接收params参数 */} <Route path="/home/message/detail/:id/:title" component={Detail}></Route>
-
第三步:组件获取参数
// 组件内 this.props.match.params 即为react封装好的params对象 const {id, titel} = this.props.match.params
Detail组件index.jsx组件获取和展示参数如下所示源代码2.1-1如下所示:
import React, { Component } from 'react'
const data = [
{id: 1, content: '学习 Java'},
{id: 2, content: '学习 Python'},
{id: 3, content: '学习 React'},
]
export default class Detail extends Component {
render() {
// console.log(this.props);
let {id, title} = this.props.match.params
id = id - 0
const detail = data.find((detail) => {
return detail.id === id
})
return (
<ul>
<li>ID: {id}</li>
<li>TITLE: {title}</li>
<li>CONTENT: {detail.content}</li>
</ul>
)
}
}
2.2 传递search参数
-
第一步:路由链接向路由组件传递search参数
{/* 格式:/} <Link to="/path1/path2/.../pathn/?参数1=值1&参数2=值2&...&参数n=值n"></Link> {/* 示例:/} {/* 向路由组件传递params参数 */} <Link to={`/home/message/detail/?id=${msg.id}&title=${msg.title}`}>{msg.title}</Link>
-
第二步:接受search参数无需声明
{/* */} <Route path="/path1/path2/.../pathn" component={组件}></Route> {/* 示例 */} {/* 声明接收params参数 */} <Route path="/home/message/detail" component={Detail}></Route>
-
第三步:组件获取参数
// 组件内 this.props.location.search 为接受的search字符串,形式:?参数1=值1&参数2=值2&... // 需要自己处理或者第三方库 const {search} = this.props.location
Detail组件index.jsx组件获取和展示参数如下所示,其他同上源代码2.1-2如下所示:
let {id, title} = qs.parse(this.props.location.search, {ignoreQueryPrefix: true})
2.3 传递state参数
注:此state为组件state参数不是组件的state属性。
-
第一步:路由链接向路由组件传递state参数
{/* 格式:/} <Link to={{pathname: "/path1/path2/.../pathn, state: {参数1: 值1, 参数2: 值2, ...}}}></Link> {/* 示例:/} {/* 向路由组件传递state参数 */} <Link to={{pathname: '/home/message/detail', state: msg}}>{msg.title}</Link>
-
第二步:接受search参数无需声明
{/* 格式 */} <Route path="/path1/path2/.../pathn" component={组件}></Route> {/* 示例 */} {/* 无需声明接收state参数 */} <Route path="/home/message/detail" component={Detail}></Route>
-
第三步:组件获取参数
// 组件内 this.props.location.state 即为接受的state参数对象 const {id, title} = this.props.location.state
Detail组件index.jsx组件获取和展示参数如下所示,其他同上源代码2.1-2如下所示:
// 接收state参数
let {id, title} = this.props.location.state
2.4 路由参数总结
- 使用形式
- params参数传递
- 路由链接传递参数:
<Link to="/demo/test/4/aaa">测试</Link>
- 路由组件声明加收参数:
<Route path="/demo/test/:id/:title" component={Test} />
- 组件接受参数:
let {id, title} = this.props.match.params
- 路由链接传递参数:
- search参数传递
- 路由链接传递参数:
<Link to="/demo/test/?id=1&title=xxx">测试</Link>
- 注册路由组件(无需声明):
<Route path="/demo/test" component={Test} />
- 组件接受参数:
let {search} = this.props.locaiton
,然后解析
- 路由链接传递参数:
- state参数
- 路由链接传递参数:
<Link to={{pathname: '/demo/test', state: {id: 1, title: 'xxx'}}}>测试</Link>
- 注册路由组件(无需声明):
<Route path="/demo/test" component={Test} />
- 组件接受参数:
let {id, title} = this.props.location.state
- 注:刷新也可以保住参数*,因为路由器是BrowserRouter,react维护history;但是如果清空缓存,参数丢失。
- 路由链接传递参数:
- 比较
- params传参:路径携带参数;
- search传参:路径携带参数,接受参数后需要另外解析;
- state传参:适用于参数具有一定保密性需求,不希望对外暴露场景
结语
❓QQ:806797785
⭐️源代码仓库地址:https://github.com/gaogzhen/react-staging.git
参考:
[1]React视频教程[CP/OL].2020-12-15.p85-89.
[2]React官网[CP/OL].