在传统的网页中,我们可能需要很多个
html
页面来实现我们的功能,这种应用也被称为多页面应用(MPA)。
单页面SPA
单页面应用是和多页面应用相对应的一种应用,其本身是在浏览器本身而不是在服务端执行逻辑,在初始页面加载完毕之后,只有数据来回的发送,而不会将整个html
文件进行发送
路由
什么是路由
在多页面中,要呈现不同的类型就是切换不同的html
文件进行显示,但是在单页面应用中,页面内容的切换依靠的是加载不同的内容以及对应的js
文件来实现的。
基本使用
由于在学习
React
的时候,react-dom-router
的v6
版本已经成为默认版本,但是学习的还是v5
版本,因此我们下载依赖的时候需要指定对应的版本号进行下载。
npm install react-dom-router@5
引入react-router-dom
库,暴露一些属性Link,BrowserRouter...
等等
明确好导航区和内容区之后就可以编写代码了
导航区
<Link className="list-group-item" to="/about">About</Link>
同时我们需要用 Route
标签,来进行路径的匹配,从而实现不同路径的组件切换
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
如果单单只有上面的代码,是不够的。我们需要将所有的路由都交由一个统一的路由器进行管理。注意是统一的路由器。而为了避免不断更换路由器的位置,我们可以直接将路由器放在<App />
组件中,从而其他所有的组件都会被这个统一的路由器所管理。
路由组件和一般组件
在我们前面的内容中,我们是把组件 Home 和组件 About 当成是一般组件来使用,我们将它们写在了 src 目录下的 components 文件夹下,但是我们又会发现它和普通的组件又有点不同,对于普通组件而言,我们在引入它们的时候我们是通过标签的形式来引用的。但是在上面我们可以看到,我们把它当作路由来引用时,我们是通过{Home}
来引用的。
最重要的一点是,他们接收到的
props
不同
- 在一般组件中,如果我们不进行传递,那么就不会收到
props
- 在路由组件中,会统一的收到三个固定的属性:
history
、location
、match
这三个路由上的比较重要的参数。
路由匹配
React
中路由共有两种匹配形式
- 精确匹配
- 模糊匹配
默认使用的是模糊匹配
- 模糊匹配:在匹配路由的时候,只要有匹配的就可以了。
- 精确匹配:必须完全相同,才能够匹配上。
重定向路由
有时候我们需要配置首页,或者将某个页面进行重定向。这个时候就需要使用到路由重定向
<Redirect to="/home" />
嵌套路由
有的时候我们在某个路由页面中,可能需要根据路径的不同,在内容区显示不同的内容。这里就需要使用到二级路由。
需要注意的是,由于多级路由的匹配是存在顺序的,比如我们想要访问
/home/news
,那么会首先匹配/home
组件,然后再继续匹配/news
。所以/home
路由上一定不能开启精确匹配,否则就不会继续匹配下去了。
<div>
<h2>Home组件内容</h2>
<div>
<ul className="nav nav-tabs">
<li>
<MyNavLink className="list-group-item" to="/home/news">News</MyNavLink>
</li>
<li>
<MyNavLink className="list-group-item " to="/home/message">Message</MyNavLink>
</li>
</ul>
{/* 注册路由 */}
<Switch>
<Route path="/home/news" component={News} />
<Route path="/home/message" component={Message} />
</Switch>
</div>
</div>
路由传参
路由传参按照参数类型的不同,可以分为如下三种:
<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
然后在注册路由的时候,我们可以通过:数据名
来接收数据
<Route path="/home/message/detail/:id/:title" component={Detail} />
这样就配置了在路由组件中接受传递的参数,我们可以打印路由组件的props
来查看接收到的参数
我们传递的数据被接收到了对象的 match 属性下的 params 中
可以直接拿到数据,并渲染页面
const { id, title } = this.props.match.params
const findResult = DetailData.find((detailObj) => {
return detailObj.id === id
})
查询参数
有一定后端经验就能知道,查询参数一般是在路径后使用
?
来进行参数的传递
<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>
使用search
方式传递的参数,不用再在注册路由的时候进行配置,而是可以直接在组件中进行获取。
但是我们拿到的是上面那一串字符串,需要将字符串转化成对象的形式。这里可以直接使用React
自带的querystring
这个库来进行转化。
import qs from 'querystring'
const { search } = this.props.location
const { id, title } = qs.parse(search.slice(1))
状态参数
类似于后端开发中使用
body
来传递参数,并不会直接将参数暴露在路径上,而是在内存中的进行状态的传递,使用内部的状态来进行维护。
<Link to={{ pathname: '/home/message/detail', state: { id: msgObj.id, title: msgObj.title } }}>{msgObj.title}</Link>
如上所示,我们在配置Link
跳转的时候,to
属性不再是简单的字符串,而是传递一个路由对象,包括:
- 跳转地址名
- state参数
和查询参数相似的是,使用状态参数时,我们一样不需要在注册路由的时候,声明接收
const { id, title } = this.props.location.state