在传统的网页中,我们可能需要很多个html页面来实现我们的功能,这种应用也被称为多页面应用(MPA)。

单页面SPA

单页面应用是和多页面应用相对应的一种应用,其本身是在浏览器本身而不是在服务端执行逻辑,在初始页面加载完毕之后,只有数据来回的发送,而不会将整个html文件进行发送

路由

什么是路由

在多页面中,要呈现不同的类型就是切换不同的html文件进行显示,但是在单页面应用中,页面内容的切换依靠的是加载不同的内容以及对应的js文件来实现的。

基本使用

由于在学习React的时候,react-dom-routerv6版本已经成为默认版本,但是学习的还是v5版本,因此我们下载依赖的时候需要指定对应的版本号进行下载。

  1. npm install react-dom-router@5

引入react-router-dom库,暴露一些属性Link,BrowserRouter...等等
明确好导航区和内容区之后就可以编写代码了

导航区

  1. <Link className="list-group-item" to="/about">About</Link>

同时我们需要用 Route 标签,来进行路径的匹配,从而实现不同路径的组件切换

  1. <Route path="/about" component={About}></Route>
  2. <Route path="/home" component={Home}></Route>

如果单单只有上面的代码,是不够的。我们需要将所有的路由都交由一个统一的路由器进行管理。注意是统一的路由器。而为了避免不断更换路由器的位置,我们可以直接将路由器放在<App />组件中,从而其他所有的组件都会被这个统一的路由器所管理。

路由组件和一般组件

在我们前面的内容中,我们是把组件 Home 和组件 About 当成是一般组件来使用,我们将它们写在了 src 目录下的 components 文件夹下,但是我们又会发现它和普通的组件又有点不同,对于普通组件而言,我们在引入它们的时候我们是通过标签的形式来引用的。但是在上面我们可以看到,我们把它当作路由来引用时,我们是通过{Home} 来引用的。

最重要的一点是,他们接收到的props不同

  • 在一般组件中,如果我们不进行传递,那么就不会收到props
  • 在路由组件中,会统一的收到三个固定的属性:historylocationmatch这三个路由上的比较重要的参数。

React路由@v5 - 图1

路由匹配

React中路由共有两种匹配形式

  • 精确匹配
  • 模糊匹配

默认使用的是模糊匹配

  • 模糊匹配:在匹配路由的时候,只要有匹配的就可以了。
  • 精确匹配:必须完全相同,才能够匹配上。

在路由上配置exact属性,即可开启精准匹配

重定向路由

有时候我们需要配置首页,或者将某个页面进行重定向。这个时候就需要使用到路由重定向

  1. <Redirect to="/home" />

React路由@v5 - 图2

嵌套路由

有的时候我们在某个路由页面中,可能需要根据路径的不同,在内容区显示不同的内容。这里就需要使用到二级路由。

需要注意的是,由于多级路由的匹配是存在顺序的,比如我们想要访问/home/news,那么会首先匹配/home组件,然后再继续匹配/news。所以/home路由上一定不能开启精确匹配,否则就不会继续匹配下去了。

  1. <div>
  2. <h2>Home组件内容</h2>
  3. <div>
  4. <ul className="nav nav-tabs">
  5. <li>
  6. <MyNavLink className="list-group-item" to="/home/news">News</MyNavLink>
  7. </li>
  8. <li>
  9. <MyNavLink className="list-group-item " to="/home/message">Message</MyNavLink>
  10. </li>
  11. </ul>
  12. {/* 注册路由 */}
  13. <Switch>
  14. <Route path="/home/news" component={News} />
  15. <Route path="/home/message" component={Message} />
  16. </Switch>
  17. </div>
  18. </div>

路由传参

路由传参按照参数类型的不同,可以分为如下三种:

  • 路径参数
  • 查询参数
  • 状态参数

    路径参数

    我们可以将数据拼接在路由地址末尾来实现数据的传递

    这里我们需要注意的是:可以采用模板字符串以及 $ 符的方式来进行数据的获取

  1. <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>

然后在注册路由的时候,我们可以通过:数据名来接收数据

  1. <Route path="/home/message/detail/:id/:title" component={Detail} />

这样就配置了在路由组件中接受传递的参数,我们可以打印路由组件的props来查看接收到的参数
React路由@v5 - 图3
我们传递的数据被接收到了对象的 match 属性下的 params 中
可以直接拿到数据,并渲染页面

  1. const { id, title } = this.props.match.params
  2. const findResult = DetailData.find((detailObj) => {
  3. return detailObj.id === id
  4. })

查询参数

有一定后端经验就能知道,查询参数一般是在路径后使用?来进行参数的传递

  1. <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>

使用search方式传递的参数,不用再在注册路由的时候进行配置,而是可以直接在组件中进行获取。
image.png
但是我们拿到的是上面那一串字符串,需要将字符串转化成对象的形式。这里可以直接使用React自带的querystring这个库来进行转化。

  1. import qs from 'querystring'
  2. const { search } = this.props.location
  3. const { id, title } = qs.parse(search.slice(1))

状态参数

类似于后端开发中使用body来传递参数,并不会直接将参数暴露在路径上,而是在内存中的进行状态的传递,使用内部的状态来进行维护。

  1. <Link to={{ pathname: '/home/message/detail', state: { id: msgObj.id, title: msgObj.title } }}>{msgObj.title}</Link>

如上所示,我们在配置Link跳转的时候,to属性不再是简单的字符串,而是传递一个路由对象,包括:

  • 跳转地址名
  • state参数

    和查询参数相似的是,使用状态参数时,我们一样不需要在注册路由的时候,声明接收

  1. const { id, title } = this.props.location.state

React路由@v5 - 图5