React Router 4.x 开发,这些雷区我们都帮你踩过了

前言

在前端框架层出不穷的今天,React 以其虚拟 DOM 、组件化开发思想等特性迅速占据了主流位置,成为前端开发工程师热衷的 Javascript 库。作为 React 体系中的重要组成部分:React Router 也成为开发者首选的路由库,其主要功能是通过管理 url 实现组件的切换和状态的变化。

正文

在 React Router 4.x 发布之前,我们在项目中使用的是 React Router 3.x。随着第四版 React Router 的正式亮相,其精简的 API 、语义化的路由匹配方案以及动态路由等变化,都彰显着此次升级的颠覆性。所以,我们决定在新的 React 项目中使用 4.x(React Router 4.x)开发,亲身实践之后发现: 4.x 不仅是 API 的简单改变,还有整个设计理念的变化;初次使用确实有一些别扭,更可怕的是按照 API 文档写出的代码,有时运行时会出现一些莫名其妙的红色错误(此刻的心情 down 到谷底~)。为了避免大家在使用时遇到同样的问题多绕弯子,我们把开发过程中遇到的问题以及相应的解决方法做了汇总。

4.x 使用问题汇总

1. 包引用方式

在之前的 3.x 中,在入口文件中定义路由时,我们会这么写:

但是保存后运行发现页面报错了,如下图所示:

解决方法:

页面显示正常,问题解决。接下来我们对该解决方法进行详细的解释:

4.x 中采用了单代码仓库模型架构,所以里面包含了若干个相互独立的包,如下所示:

react-routerreact-router-domreact-router-nativereact-router-reduxreact-router-config
react-routerreact-router-domreact-router-domreact-router-dom

使用方法:

2. 页面中多个模块同时渲染问题

我们同时定义了多个模块,当路由切换时发现这些模块会同时渲染出来。比如像下面这样定义:

path="/card"path="/"path="/card"path="/"
exact

完美!模块可以实现独立渲染了。我们来看下这样解决问题的原因:

<BrowserRouter>
pushStatereplaceStatepopstate
  • basename: string
urlbasenameurl
  • getUserConfirmation: func
window.confirm
  • forceRefresh: bool
truetrue
  • keyLength: number
location.keylocation.keykey
  • children: node

渲染单一子组件(元素)。

<HashRouter>
hashlocation.keylocation.state
Routepath

<Route>  属性值主要有:

  • path: string
path-to-regexppath
  • exact: bool
truelocation.pathname

  • strict: bool
truelocation.pathname

exacttrue
React component
match
matchlocationhistory

需要注意的是 :每一种渲染方法都有其适用背景, <Route component>  的优先级比  <Route render>  高,而他们又都优先于  <Route children>  ,所以在同一个  <Route>  应该只使用一种方法,我们大多数使用的是 component 方法。

/card/card
  • children: node

3. 如何定义默认访问页面

当用户手动修改 url 时,有时我们需要定义一个默认页面,重新引导用户的操作,这个该如何实现呢?

/test
history

其常用的属性是:

  • to: string

重定向的 url 地址。

  • to: object
location
  • push: bool
true
  • from: string

需要匹配的将要被重定向的路径。

pathfrompathfrom

4. 路由激活状态的控制

activeClassNameactiveStyleStyle
  • activeClassName: string
active
  • activeStyle: object

导航选中时的样式。

  • exact: bool
true
  • strict: bool
true
  • isActive: func

用于添加页面激活时的操作逻辑。

5. 页面跳转

在 3.x 中,跳转页面可以使用以下方式:

push

  

针对该问题有以下两种解决方法:

(1)使用 history 控制路由的跳转
history
historyhistoryhistory
React Native
history
lengthactionlocationpush(path, [state])replace(path, [state])go(n)goBack()goForward()block(prompt)
historyhistory.locationproplocation
Contextrouter
Reactcontext

6. 切换路由后,页面仍然停留在上一个页面的位置

由 A 页面跳转到 B 页面,B 页面停留在 A 页面的位置,没有返回到顶部。

React RouterwithRouterwithRoutermatchlocationhistorywithRouter

这样就可以获取到 MyComponent 组件的路由信息了。

withRouterScrollToTopwithRouterpropslocation
ScrollToTop
(2)在定义路由处引用该组件,例如:

这样处理之后,当跳转页面时都会自动回到该页面的顶部位置。

7. 页面之间如何传值?

问题背景:当路由发生跳转时我们可能需要携带一些参数。

props
props.params
path

跳转 UserPage 页面时,可以这样写:

this.props.params.name

上面的方法可以传递一个或多个值,但是每个值的类型都是字符串,没法传递一个对象。如果要传的话可以将 json 对象转换为字符串,传递过去之后再将 json 字符串转换为对象。

query
queryurlqueryurl
state
statepost

在实际的项目开发中,大家可以根据项目需要选择合适的传值方法。

在开发过程中使用是没有问题的,但是将页面上传至服务器之后,问题就来了:用户访问的资源不存在,页面是空白的。

historyexample.com/list/123

解决方法:

http://www.example.com/http://www.example.com/#/Reactwebpack-dev-server

9. React Router 4.x 如何配置按需加载?

问题背景:当访问首页时会一次性请求所有的 js 资源,这会大大影响页面的加载速度和用户体验。所以添加按需加载功能是必要的。

bundle loaderbundle loader

解决方法:配置按需加载的步骤如下:

bundle-loader
Bundle.js
loadpropsload
app.jsx
bundle-loader
webpack.config.js

这样配置之后,打包出来的 js 文件已经进行了拆分,每个页面对应一个自己的 js ,当访问该页面时才加载相应的资源。

this.props.history.push()
this.props.history.push中'push'is undefined
this.props.history.push()this.props.history
withRouter
React Router

以上列出的内容就是我们在使用 4.x 开发时遇到的一些问题,针对每个问题不仅给出了解决方法,还介绍了解决方法中涉及到的知识点。对于一些未介绍到的内容,大家可以移步官网进行深度学习(见扩展阅读 [2])。

小结

对于新项目来说,使用 React Router 4.x 进行开发是一个不错的选择。因为其组件化的思想和 React 很像,学习起来比较容易、上手快。除了官网 [2] ,扩展阅读中我们还给出了 React Router 4.x 的其他学习文档 [3][4],供大家参考。值得注意的是,上述问题解决方法中的示例代码使用的是 React v16 版本,在实际使用时需要结合自己的环境进行适当修改。

React Router 4.x 此次带来的改变是颠覆性的,对于我们使用者来说是一种挑战,同时也是一种知识的有趣探索。组件化路由设计理念和动态路由的配置给我们的项目开发带来了更大的灵活性。文中在介绍问题解决方法时对一些 4.x 的 API 做了简要的介绍,对于一些更细节化的东西,需要我们移步官网进行深入的学习,然后再慢慢的探索。React Router 的作者说过版本号要永远和 React 保持一致,所以相信我们的 React Router 探索之旅将会一直进行着……同志们,Hold On!

好了,关于 React Router 4.x 开发实践中遇到的问题就介绍到这里了,如有任何疑问,欢迎留言。

扩展阅读

有兴趣欢迎关注我们的公众号:全栈探索。欢迎交流。