前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React Router3到5 升级小记

React Router3到5 升级小记

作者头像
zz_jesse
发布2020-03-17 17:04:33
2.2K0
发布2020-03-17 17:04:33
举报
文章被收录于专栏:前端技术江湖前端技术江湖

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

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

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

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

导入的包变了

代码语言:javascript
复制
//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 表示是否替换掉原地址

代码语言:javascript
复制
//v3
import {Link} from react-router;

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

Router 组件变化

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

看代码更清晰

代码语言:javascript
复制
//v3
<Router history={browserHistory}></Router>
<Router history={hashHistory}></Router>

//v4+ v5+
<BrowerRouter></BrowerRouter>
<HashRouer></HashRouer>

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

Route 升级了

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

组件渲染方式1

代码语言:javascript
复制
<Route component={Home}/>

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

组件渲染方式2

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

代码语言:javascript
复制
<Route render={(props) => (<Home></Home>)/>

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

组件渲染方式3

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

Switch 组件的坑

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

举个栗子

代码语言:javascript
复制
let routes = (
  <div>
    <Route path="/about" component={About} />
    <Route path="/:user" component={User} />
    <Route component={NoMatch} />
  </div>
);

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

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

代码语言:javascript
复制
let routes = (
  <Switch>
    <Route path="/about" component={About} />
    <Route path="/:user" component={User} />
    <Route component={NoMatch} />
  </Switch>
);

此时<Route path="/about" />将会被匹配到,后面 Switch 会停止继续后面的匹配,只渲染About组件。

exact 属性

问题就这样解决了吗?

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

代码语言:javascript
复制
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属性了,表示是否精确匹配,让路由的匹配更严谨。

代码语言:javascript
复制
let routes = (
  <Switch>
    <Route path="/" exact component={Index} />
    <Route path="/about" component={About} />
    <Route path="/:user" component={User} />
    <Route component={NoMatch} />
  </Switch>
);

不再强制集中式路由

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

v3下的代码

代码语言:javascript
复制
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下的代码

代码语言:javascript
复制
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 已经支持数组。

代码语言:javascript
复制
// 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 取值

代码语言:javascript
复制
//v3
this.props.params

//v4 v5
this.props.match.params

location.query 取值

代码语言:javascript
复制
//V3 获取query可以这么获取
this.props.location.query

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

location.action 属性转移

代码语言:javascript
复制
// V3 获取location的action
this.props.location.action

//V4 5
this.props.history.action

嵌套路由

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

代码语言:javascript
复制
<Router history={hashHistory}>
  <Route path='/' component={App}>
    <Route path='a' component={A} />
    <Route path='b' component={B} />
  </Route>
</Router>

V4 V5中不在支持 Route 嵌套

代码语言:javascript
复制
<Switch>
           <Route path="/" component={BaseLayout} />
</Switch>
代码语言:javascript
复制
//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 里实现组件按需加载还是很方便的,因为提供了特定的方法。

代码语言:javascript
复制
const Route = {
  path: '/a',
  getComponents(location, callback) {
    require.ensure([], function (require) {
      callback(null, require('./pages/a'))
    })
  }
}
<Route {...Route} ></Route>

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

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

代码语言:javascript
复制
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升级改动不仅仅是上面这些,整体改动真的很大。与其说是升级不如说是重写,难怪很多人不愿意升级,升级了才知道升级的痛。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端技术江湖 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导入的包变了
  • Router 组件变化
  • Route 升级了
    • 组件渲染方式1
      • 组件渲染方式2
        • 组件渲染方式3
        • Switch 组件的坑
          • exact 属性
          • 不再强制集中式路由
          • v5 一个新特性
          • props.params 取值
          • location.query 取值
          • location.action 属性转移
          • 嵌套路由
          • Route 监控事件移除
          • 按需加载
          • 小结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档