• ReactRouter 4 前瞻 2016-09-21 08:32:42
    ReactRouter 4 这次改动挺大的,后面又要折腾一次了!!作者:杨森链接:https://zhuanlan.zhihu.com/p/22490775要问用 React 技术栈的前端同学对哪个库的感情最复杂,恐怕非 ReactRouter 莫属了。早在 React 0.x ...
    ReactRouter 4 这次改动挺大的,后面又要折腾一次了!!


    作者:杨森
    链接:https://zhuanlan.zhihu.com/p/22490775

    要问用 React 技术栈的前端同学对哪个库的感情最复杂,恐怕非 ReactRouter 莫属了。早在 React 0.x 时代,ReactRouter 就凭借与 React 核心思想一致的声明式 API 获得了大量开发者的喜爱。后续更是并入 reactjs group 并有 React 核心开发成员参与,俨然是 React 官方路由套件一样的存在。

    然而从 1.x 版本起,ReactRouter 的洪荒之力就开始慢慢爆发,目前最稳定的版本已经是 2.8.1,而下一个正式版本将是 —— 没错,正如你在标题里看到的那样 —— 4.0.0。先收拾一下你崩溃的心情,让我们来看看这一切到底是怎么回事。

    ReactRouter 3 去哪儿了

    从 2.x 直接跨入 4.x,ReactRouter 的 maintainer 数学还不至于那么差,那这一切都是为什么呢?事实上 3.x 版本相比于 2.x 并没有引入任何新的特性,只是将 2.x 版本中部分废弃 API 的 warning 移除掉而已。按照规划,没有历史包袱的新项目想要使用稳定版的 ReactRouter 时,应该使用 ReactRouter 3.x。

    目前 3.x 版本也还处于 beta 阶段,不过会先于 4.x 版本正式发布。如果你已经在使用 2.x 的版本,那么升级 3.x 将不会有任何额外的代码变动。

    为什么又要大改 API

    ReactRouter 的 API 是出了名的善变,这一点我已经在之前的博文中吐槽过一次了。没想到连 React 都稳定的在 15.x 版本中维护了这么久,ReactRouter 还是想要搞点大新闻。

    根据 ReactRouter 核心开发者 ryanflorence 的说法,ReactRouter 4.x 之所以要大刀阔斧的修改 API,主要是为了『声明式的可组合性(Declarative Composability)』。怎么理解声明式的可组合性呢?实际上当你在写 React 组件时,就不知不觉的利用了这一特性。

    function ComponentA() {  
      return <div>A</div>;
    }
    
    function ComponentB() {  
      return <div>B</div>;
    }
    
    function Page() {  
      return <div><ComponentA /><ComponentB /></div>;
    }
    

    正如上面的代码片段,在 Page 组件中你可以方便的将任意组件在 render 方法中渲染出来。但是这种特性遇到 ReactRouter 时,你只能把匹配当前路由的组件用this.props.children(最早的时候是 this.props.routerHandler,有多少人还有印象)渲染 。

    此外,ReactRouter 虽然宣称是声明式的路由库,但仍然提供了不少非声明式的 API,其中路由组件的生命周期方法就是最典型的例子。其实我们不难想到,明明用来渲染的 React 组件本身已经有了一套完备的生命周期方法(componentWillMount、componentWillUnmount 等),为什么还需要 ReactRouter 提供的什么 onEnter 和 onLeave 呢?

    当然,这一切都是 ryanflorence 个人的说法,不知道又有多少人真的会为了追求纯正的 declarative 花时间去重构代码兼容 ReactRouter 4 呢?

    ReactRouter 4 有什么变化

    虽然目前还是 alpha 版本,但是 ReactRouter 4 的 API 已经有了雏形,其官方文档也有不少带 demo 的例子,下面简单总结一下 ReactRouter 4 的变化。

    更少的 API

    先来看看目前 ReactRouter 2 的 API 列表:


    再看看 4.x 计划中的 API:

    直观看起来 API 确实少了不少,但这也意味着使用了被废弃的 API 将会有更大的重构工作量。不,实际上即使用了没有被废弃的 API,也会有很大的重构工作量。但是对于新手来说,学习成本相对会比较低。

    <Router> 变身为容器

    在目前的 API 中,<Router> 组件的 children 只能是 ReactRouter 提供的各种组件,如 <Route>、<IndexRoute>、<Redirect>等。而在 ReactRouter 4 中,你可以将各种组件及标签放进 <Router> 组件中,他的角色也更像是 Redux 中的 <Provider>。

    不同的是 <Provider> 是用来保持与 store 的更新,而 <Router> 是用来保持与 location 的同步。

    以下为新版 ReactRouter 可能的用法:

    <Router>  
      <div>
        <h2>Accounts</h2>
        <ul>
          <li><Link to="/netflix">Netflix</Link></li>
          <li><Link to="/zillow-group">Zillow Group</Link></li>
          <li><Link to="/yahoo">Yahoo</Link></li>
          <li><Link to="/modus-create">Modus Create</Link></li>
        </ul>
    
        <Match pattern="/:id" component={Child} />
      </div>
    </Router>  
    

    不过这样的变动将会导致一个很严重的问题:由于路由定义里不再是纯粹的路由相关的组件,你无法在一个文件中(通常是用来定义路由的 routes.js)看到整个 App 的路由设计及分布。

    目前 ReactRouter 提供了一个工具库来解决将完整的路由定义转换为 <Match> 组件的问题,但是粗略的看了一下用法感觉还是比较别扭,期待正式发布时能有更好的解决方案。

    再见 <Route>,你好 <Match>

    ReactRouter 中被使用最多的 <Route> 组件这次没有幸免,取而代之的是 <Match> 组件。那么 <Match> 究竟有什么不同呢?

    1. pattern 取代 path

    很大程度上这只是为了配合 Match 这个名称的转换而已,实际功能与 path 无异。

    <Match pattern="/users/:id" component={User}/>  
    

    2. component 还是 component,components 没了

    判断路由命中时该渲染哪个组件的 props 还是叫 component,但是为一个路由同时提供多个命名组件的 props components 没有了。下文会详细介绍在 ReactRouter 中如何解决一个路由下渲染多个组件的问题。

    3. 使用 render 渲染行内路由组件

    能够更自由的控制当前命中组件的渲染,以及可以方便的添加进出的动画。

    // convenient inline rendering
    <Match pattern="/home" render={() => <div>Home</div>}/>
    
    // wrapping/composing
    const MatchWithFade = ({ component:Component, ...rest }) => (  
      <Match {...rest} render={(matchProps) => (
        <FadeIn>
          <Component {...matchProps}/>
        </FadeIn>
      )}/>
    )
    
    <MatchWithFade pattern="/cool" component={Something}/>  
    

    <Miss> 取代曾经的 <NotFoundRoute>

    早在 0.x 时代,ReactRouter 提供了 <NotFountRoute> 来解决渲染 404 页面的问题。不过这一组件在 1.x 时就被移除了,你不得不多写若干行代码来解决这个问题。

    // 如果想要展示一个 404 页面(当前 URL 不变)
    <Route path='*' component={My404Component} />
    
    // 如果想要展示一个 404 页面(当前 URL 重定向到 /404 )
    <Route path='/404' component={My404Component} />  
    <Redirect from='*' to='/404' />  
    

    在 ReactRouter 4 中,你可以省点儿事直接用 <Miss> 组件。

    const App = () => (  
      <Router>
        <Match pattern="/foo"/>
        <Match pattern="/bar"/>
        <Miss component={NoMatch}/>
      </Router>
    )
    
    const NoMatch = ({ location }) => (  
      <div>Nothing matched {location.pathname}.</div>
    )
    

    ReactRouter 4 的大杀器:一个路由,多次匹配

    在上文中我们提到过,目前 ReactRouter 匹配到某个路由时,将直接渲染通过 component 定义的组件,并把命中的子路由对应的组件作为 this.props.children 传入。

    在前端 App 日益复杂的今天,一条路由的改变不仅仅简单的是页面的切换,甚至可能精细到页面上某些组件的切换。

    让我们直接看下面的代码:

    // 每条路由有两个组件,一个用于渲染 sidebar,一个用于渲染主页面
    const routes = [  
      { pattern: '/',
        exactly: true,
        sidebar: () => <div>Home!</div>,
        main: () => <h2>Main</h2>
      },
      { pattern: '/foo',
        sidebar: () => <div>foo!</div>,
        main: () => <h2>Foo</h2>
      },
      { pattern: '/bar',
        sidebar: () => <div>Bar!</div>,
        main: () => <h2>Bar</h2>
      }
    ]
    
    <Router history={history}>  
      <div className="page">
        <div className="sidebar">
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/foo">Foo</Link></li>
            <li><Link to="/bar">Bar</Link></li>
          </ul>
    
          /* 对当前路由进行匹配,并渲染侧边栏 */
          {routes.map((route, index) => (
            <Match
              key={index}
              pattern={route.pattern}
              component={route.sidebar}
              exactly={route.exactly}
            />
          ))}
        </div>
    
        <div className="main">
          /* 对当前路由进行匹配,并渲染主界面 */
          {routes.map((route, index) => (
            <Match
              key={index}
              pattern={route.pattern}
              component={route.main}
              exactly={route.exactly}
            />
          ))}
        </div>
      </div>
    </Router>  
    

    通过上面的代码片段我们可以看出,<Match> 的设计理念完全不同于 <Route>。使用 <Match>可以让我们在当前路由中尽情的匹配并渲染需要的组件,无论是需要渲染 Sidebar、BreadCrumb 还是主界面。

    若使用现有的 ReactRouter API,只能通过当前路由匹配主界面对应的组件,至于 Sidebar 和 BreadCrumb,只能传入当前的 pathname 手动进行匹配。由此可见 <Match> 将会为此类需求带来极大的便利。

    其他疑惑

    当然,还有几个大家普遍关心的问题官方文档中也有所提及:

    1. ReactRouter 的 API 是否还会有大的变化?

    答:只要 React 的 API 不变,这一版的 API 也不会变。

    2. 是否有对 Redux 的支持?

    答:将提供一个受控的 <ControlledRouter>,支持传入一个 location。(作者注:这下真的不需要 react-router-redux 了,撒花!)

    3. 新版是否对滚动位置管理添加支持?

    答:将会对 window 和独立组件的滚动位置提供管理功能。(作者注:目前在不添加额外配置的情况下,路由切换时并不会恢复滚动位置)

    ReactRouter 4 小结

    了解了这么多 ReactRouter 4 的内容,你是否喜欢新版的 API 设计呢?

    其实从 ReactRouter 4 的这些变动不难看出,ReactRouter 正在努力的朝纯声明式的 API 方向迈进,一方面减少不必要的命令式 API,一方面也提供更语义化的路由匹配方案。

    此外新的 ReactRouter 也提供了非常强大的动态路由能力,甚至对嵌套路由也有所支持,这也是一个复杂的前端应用所必须的功能。

    参考资料

    1. ReactRouter 4 文档
    2. ReactRouter 4 Github repo
    3. ReactRouter

    注:本文首发于我的个人博客 undefinedblog,欢迎大家捧个人场。

    又注:访问 reactchina.com 有惊喜

    Reactreact

    展开全文
  • react router4介绍 2018-08-01 20:12:02
    React Router4是一个流行的纯React重写的包。现在的版本中已不需要路由配置,现在一切皆组件。 本文涵盖了开始使用React Router构建网站所需要的一切知识。我们将会为本地运动队制作一个网站。 代码 想看网站最终...
  • React Router v4 入坑指南 2018-11-19 10:25:13
    万恶的根源 距离React Router v4 正式发布也已经过去三个月了,这周把一个...(ヾ(。ꏿ﹏ꏿ)ノ゙咦,此刻相信机智如我的你也会发现,ReactRouter v3 去哪儿了?整丢了??巴拉出锅了???敢不敢给我个完美的解释!...
  • React router 4.x 2019-05-10 23:32:15
    React router 在gitHub上,学会找官方文档,看文档 安装 npm install react-router-dom --save 导入模块 import { BrowserRouter as Router, Route,Link } from &amp;amp;amp;amp;quot;react-router-dom&...
  • React Router 4 简易入门 2018-05-17 11:41:50
    React Router4是一个流行的纯React重写的包。现在的版本中已不需要路由配置,现在一切皆组件。本文涵盖了开始使用React Router构建网站所需要的一切知识。我们将会为本地运动队制作一个网站。代码想看网站最终效果,...
  • React Router4 2019-06-15 14:09:09
    React Router4是一个流行的纯React重写的包。现在的版本中已不需要路由配置,现在一切皆组件。 本文涵盖了开始使用React Router构建网站所需要的一切知识。我们将会为本地运动队制作一个网站。 代码 想看网站最终...
  • 关于 React Router 4 的一切 2017-08-19 13:12:34
    我在 React Rally 2016 大会上第一次遇到了 Michael Jackson,不久之后便写了一篇 an article on React Router 3。Michael 与 Ryan Floren
  • react router 配置404页面 2019-07-18 01:37:46
    使用Vue相关的技术栈2年左右了,在路由管理上一直用的比较得心应手,现在的项目使用react开发,路由自然也就切换到了react router,所用版本为react router 4 在Vue router配置中,我们可以很简单的配置出404页面 ...
  • react router4 js控制跳转 2018-03-08 10:13:58
    react 16.2.0;react-router 4.2.0;react-router-dom 4.2.2本示例演示从开始...很简单,直接看代码关键点:相对react-router之前版本,react-router4通过withRouter获取historyimport React from 'react';import Rea...
  • React-router 4路由监听 2019-06-10 12:33:07
    React-router 4 React Router4是一个纯React重写的包,现在的版本中已不需要路由配置,一切皆组件。 问题出发点 最近在一个新的H5项目中使用了react router 4 ("react-router-dom": "^4.2.2"),项目中的一部分页面是...
  • 参考文档: react router 文档 import React from "react" import { withRouter } from "react-router-dom" class ShowTheLocation extends React.Component { toOtherRoute = () => { const urlObj = { ....
  • React Router 主要使用场景是单页面富应用(SPA)。实现有两种,一种是利用url的hash,就是常说的锚点(#),JavaScript通过hashChange事件来监听url的改变;另一种是HTML5的History模式,它使url看起来像普通网站那样,...
  • React Router 4 发布,我能清晰地感觉到来自 Twitter 大家对新版本中其 大量的修改 的不同声音。诚然,我在学习 React Router 4 的第一天,也是非常痛苦的,但是,这并不是因为看它的 API,而是反复思考使用它的模式...
  • 其实 React Router4 推出了好久了,不过一直没有刻意去使用它,直到最近重构某个项目才开始使用,也遇到过一些坑,在学习过程中读到这篇文章 All About React Router 4,觉得比较好,翻译如下。 我是在 2016 年的 ...
  • React-router4的简单理解 2018-07-30 17:29:21
    和之前版本不兼容,浏览器和RN均兼容React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件。所以 RR4 只是一堆 提供了导航功能的组件(还有若干对象和方法),具有声明式(引入即...
  • React Router 再 v3 版本之前 是有 onEnter 钩子函数的,也支持静态路由配置;,但到了 v4 版本后钩子函数被移除,官方说是为了将此提供给开发者,由开发者自由发挥。既然如此我们就只能自己实现,目前网上有很多...
  • React - Router4 2018-05-04 14:00:09
    安装React Router被拆分成三个包:react-router,react-router-dom和react-router-native。react-router提供核心的路由组件与函数。其余两个则提供运行环境(即浏览器与react-native)所需的特定组件。进行网站(将会...
  • React实战-通过ReactRouter-example分析Router用法 在我们了解完一种新的Web框架或者语言后,总是从各个单个的知识点了解,做着一个一个Demo,等到我们开始去做一个项目或产品时,需要解决的问题又趋于相同。我们常常...
1 2 3 4 5 ... 20
收藏数 12,215
精华内容 4,886