React Router3到5 升级小记

简介: 现在都 React Router 5 了,你是不是还在用v3呢?不光是你在用,我们很多项目也在用,懒得升级,感觉改动太大,升级了后谁知道会出什么问题,别没事找事。毕竟v4是两年前的了,再不升级真的就有点说不过去了,直接拿一个小项目开刀,直接3-5吧,整体来说还好,v5版完全向下兼容react15,所以如果你的 react 是15的话没啥影响。这里就简单的总结下,这次升级的一些内容。

现在都 React Router 5 了,你是不是还在用v3呢?

不光是你在用,我们很多项目也在用,懒得升级,感觉改动太大,升级了后谁知道会出什么问题,别没事找事。

毕竟v4是两年前的了,再不升级真的就有点说不过去了,直接拿一个小项目开刀,直接3-5吧,整体来说还好,v5版完全向下兼容react15,所以如果你的 react 是15的话没啥影响。

这里就简单的总结下,这次升级的一些内容。

导入的包变了


//V3 下
npm i react-router
//V5 下
npm i react-router-dom

react-router为核心库,运行于浏览器端就用react-router-dom,如果是native端 ,那就用react-router-native,安装react-router-dom后会自动安装react-router

所以Link组件的导入也变了,同时增加了属性 replace 表示是否替换掉原地址

//v3
import {Link} from react-router;
//v4 v5
import { Link } from 'react-router-dom';

Router 组件变化


v5里没有 Router 组件,换成更具体的组件了,HashRouerBrowserRouter

看代码更清晰

//v3
<Router history={browserHistory}></Router>
<Router history={hashHistory}></Router>
//v4+ v5+
<BrowerRouter></BrowerRouter>
<HashRouer></HashRouer>

这个升级挺好,不用再配什么参数了

Route 升级了


Route组件和 v3 版本的 Route作用一致,都是在path匹配的 时候,渲染指定组件,但是写法上有些变化,而且增加了一些特性。

组件渲染方式1

<Route component={Home}/>

component 属性和 v3 中的 component 属性保持一致,表示path匹配的时候才会渲染的组件。

组件渲染方式2

增加了render属性,v3中不存在这个属性,render 表示在path匹配时被调用的方法,而不是创建一个组件,但是需要一个返回值,返回一个组件或者null。

<Route render={(props) => (<Home></Home>)/>
<Route render={(props) => (<div>hello,前端技术江湖</div>)/>

组件渲染方式3

新增children属性,childrenrender 一样,但是不会匹配地址,路径不匹配时 URL的match 值为 null,可以用来根据路由是否匹配动态调整UI。

Switch 组件的坑


Switch 用来渲染和 path 相匹配的第一个路由,当匹配到一个路由后就不会继续往后匹配,反之则会渲染和 path匹配的所有路由。

举个栗子

let routes = (
  <div>
    <Route path="/about" component={About} />
    <Route path="/:user" component={User} />
    <Route component={NoMatch} />
  </div>
);

根据上面的配置来说,如果此时路径是/about,那么About,User,NoMatch都会渲染,因为都会被匹配到。

那怎么才能只渲染About组件呢,那就需要使用Switch组件。

let routes = (
  <Switch>
    <Route path="/about" component={About} />
    <Route path="/:user" component={User} />
    <Route component={NoMatch} />
  </Switch>
);

此时将会被匹配到,后面 Switch 会停止继续后面的匹配,只渲染About组件。

exact 属性

问题就这样解决了吗?

在下面代码增加了新的Route, 用于渲染 Index 组件,那还能正常的渲染About组件吗。

let routes = (
  <Switch>
    <Route path="/" component={Index} />
    <Route path="/about" component={About} />
    <Route path="/:user" component={User} />
    <Route component={NoMatch} />
  </Switch>
);

结果并不会渲染About组件,而会渲染Index组件,Swith 的特性就是只渲染第一个匹配到的,因为/about也会匹配/

这个时候就需要使用exact属性了,表示是否精确匹配,让路由的匹配更严谨。

let routes = (
  <Switch>
    <Route path="/" exact component={Index} />
    <Route path="/about" component={About} />
    <Route path="/:user" component={User} />
    <Route component={NoMatch} />
  </Switch>
);

不再强制集中式路由

v3里的路由就是个配置文件,所有的路由规则都写在一起,而且必须写在一起。

v3下的代码

import { Router, Route, IndexRoute } from 'react-router'
const Layout = props => (
  <div className="Layout-box">
    <header>
      React Router 3 App
    </header>
    <main>
      {props.children}
    </main>
  </div>
)
const HomePage =() => <div>Home Page</div>
const UsersPage = () => <div>Users Page</div>
const App = () => (
  <Router history={browserHistory}>
    <Route path="/" component={Layout}>
      <IndexRoute component={HomePage} />
      <Route path="/users" component={UsersPage} />
    </Route>
  </Router>
)
render(<App />, document.getElementById('root'))

v4 v5的理念是一切都是组件,路由也是组件,那就可以随意的摆放它的位置,比如写在别的组件里。

v5下的代码

import { BrowserRouter, Route } from 'react-router-dom'
const Layout = () => (
  <div className="layout-box">
    <header>
     React Router 5 App
    </header>
    <main>
      <Route path="/" exact component={HomePage} />
      <Route path="/users" component={UsersPage} />
    </main>
  </div>
)
const HomePage =() => <div>Home Page</div>
const UsersPage = () => <div>Users Page</div>
const App = () => (
  <BrowserRouter>
    <Layout />
  </BrowserRouter>
)
render(<App />, document.getElementById('root'))

但我还是喜欢集中式的,v5里仍然可用这种方式,可能习惯了。

v5 一个新特性

这个是在 v5 里增加的,如果你想让不同的多个 path 渲染同一个组件,可以不用写多个 Routev5path 已经支持数组。

// v4 这样写
<Switch>
  <Route path="/users/:id" component={User} />
  <Route path="/profile/:id" component={User} />
</Switch>
//  v5 这样写
<Route path={["/users/:id", "/profile/:id"]} component={User} />

props.params 取值

//v3
this.props.params
//v4 v5
this.props.match.params

810925c58d156c33f4a1a5f4d638544b_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

location.query 取值

//V3 获取query可以这么获取
this.props.location.query
//V4 5 只能通过 search 来取值,一般是自己写一个方法或者使用query-string库
this.props.location.search

31c7c36b911158132d4ffab2e65c15f3_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

location.action 属性转移

// V3 获取location的action
this.props.location.action
//V4 5
this.props.history.action

ec45318348f76cb68eaef77cf7cfbc8b_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

嵌套路由


V3中使用路由嵌套是很平常的事儿,而且写起来也很简单

<Router history={hashHistory}>
  <Route path='/' component={App}>
    <Route path='a' component={A} />
    <Route path='b' component={B} />
  </Route>
</Router>

V4 V5中不在支持 Route 嵌套

<Switch>
           <Route path="/" component={BaseLayout} />
</Switch>
//BaseLayout 组件
<div className='layout'>
    <Switch>
        <Route exact path="/a" component={A} />
            <Route exact path="/b" component={B} />
            <Route exact path="/c" component={C} />
    </Switch>
 </div>

使用起来很不顺手,所以我直接放弃了嵌套的写法,不要和我一样。

Route 监控事件移除


v3中,可以使用使用 RouteonEnter, onUpdateonLeave事件来做一些事情。

v4 5中,Route的这些事件没了,不过我还没用到这些事件,只是简单的提一句。

按需加载


v3 里实现组件按需加载还是很方便的,因为提供了特定的方法。

const Route = {
  path: '/a',
  getComponents(location, callback) {
    require.ensure([], function (require) {
      callback(null, require('./pages/a'))
    })
  }
}
<Route {...Route} ></Route>

v4开始就完全不一样了,已经移除了getComponent这个属性。

这里我使用的是一个现有的库react-loadable 搞定的,当然也可以自己写一个。

import React from 'react';
import Loadable from 'react-loadable';
//加载动画
const loadingComponent =()=>{
    return (
        <div>loading</div>
    )
}
//Home.js
export default Loadable({
    loader:import('./index.js'),
    loading:loadingComponent
});
// 和路由结合
<Route path="/home" component={Home}/>

小结


v3v5升级改动不仅仅是上面这些,整体改动真的很大。与其说是升级不如说是重写,难怪很多人不愿意升级,升级了才知道升级的痛。现在都 React Router 5 了,你是不是还在用v3呢?

不光是你在用,我们很多项目也在用,懒得升级,感觉改动太大,升级了后谁知道会出什么问题,别没事找事。

毕竟v4是两年前的了,再不升级真的就有点说不过去了,直接拿一个小项目开刀,直接3-5吧,整体来说还好,v5版完全向下兼容react15,所以如果你的 react 是15的话没啥影响。

这里就简单的总结下,这次升级的一些内容。

目录
相关文章
|
11月前
|
前端开发 开发者
|
存储 资源调度 前端开发
如何升级到 React 18发布候选版
上周 react 官网 发布了react@rc 版本,该版本是候选版本(Release Candidate),这意味API已经基本稳定,跟最终版本不会有太大差别。
220 0
|
前端开发 JavaScript API
React 18 升级指南,超简单
React 18 升级指南,超简单
765 0
|
移动开发 Dart 前端开发
React Native 迎来重大架构升级,性能将大幅提升
7 月 14 日,React Native 核心团队的 Joshua Gross 在 Twitter 说,RN 的新架构已经在 Facebook 内部落地了,并且 99%的代码已经开源。这次的架构升级“蓄谋已久”,Joshua 说他们从 2018 年 1 月就开始规划了。
444 0
React Native 迎来重大架构升级,性能将大幅提升
|
前端开发 Android开发
[React Native]升级React Native版本
React Native正式版本还没发布,但是小版本基本上每个月都更新1-2次。9月11号又更新了0.33版本,其中有两个增强功能正好是项目中用到的. 添加Android6.0权限验证API Add JS library for requesting Android M Permissions (0fb2ccf) - @cmcewen Android对话框可以设置ca
1122 0
|
6天前
|
设计模式 前端开发 数据可视化
【第4期】一文了解React UI 组件库
【第4期】一文了解React UI 组件库
138 0
|
6天前
|
存储 前端开发 JavaScript
【第34期】一文学会React组件传值
【第34期】一文学会React组件传值
35 0
|
6天前
|
前端开发
【第31期】一文学会用React Hooks组件编写组件
【第31期】一文学会用React Hooks组件编写组件
37 0
|
6天前
|
存储 前端开发 JavaScript
【第29期】一文学会用React类组件编写组件
【第29期】一文学会用React类组件编写组件
39 0
|
6天前
|
资源调度 前端开发 JavaScript
React 的antd-mobile 组件库,嵌套路由
React 的antd-mobile 组件库,嵌套路由
49 0