(注:参考自官方英文文档V3.X版本)

react-router是伴随着react框架出现的路由系统,它也是公认的一种优秀的路由解决方案。在使用react-router时候,我们常常会使用其自带的路径跳转组件Link,通过<Link  to="path"></Link>实现跳转,这和传统的<a href="path"></a>何其相似!但它们到底有什么具体的区别呢?

对比<a>,Link组件避免了不必要的重渲染

A  -- 通过<a>标签实现页面跳转:(图中的例子将会在下面详细解答)


----->----->


B --通过<Link>组件实现页面跳转:


  ------>


react-router:只更新变化的部分从而减少DOM性能消耗

react的创新之处在于,它利用虚拟DOM的概念和diff算法实现了对页面的"按需更新",react-router很好地继承了这一点,譬如上图所示,导航组件和三个Tab组件(通过...,通过...,通过...)的重渲染是我们不希望看到的,因为无论跳转到页面一或是页面二,它只需要渲染一次就够了。<Link>组件帮助我们实现了这个愿望,反观<a>标签,每次跳转都重渲染了导航组件和Tab组件试想一下,在一个浩大的项目里,这多么可怕!我们的"渲染"做了许多"无用功",而且消耗了大量弥足珍贵的DOM性能!

react-router的使用

1用npm安装依赖:通过终端进入项目目录里,写入npm install react-router安装react-router;

2从react-router的包里导入自带的组件如Router,Route等,一个简单的路由组件是这样的:

import React from 'react';
import { Router, Route, browserHistory} from 'react-router'
ReactDOM.render(
    <Router history={browserHistory}>
              <Route path='/' component={App}>
                  <Route path='pageOne/:id' component={PageOne}/>
                  <Route path='pageTwo/:id' component={PageTwo} />
              </Route>
     </Router>,
  document.getElementById('root')
);

其中App和PageOne,PageTwo是已定义的react组件

react-router的两大组件--Router和Route

1.Router组件

Router组件是react-router的基础组件,它位于最外层,作用是使UI和URL保持同步,要实现这一点需要向Router组件写入history属性值,Router的history属性有两个值:browserHistory和hashHistory(注:这两个值也是从react-router包中导入的)

  • browserHistory和hashHistory的区别?

        更改路由的方式不同

     1.browserHistory 使用的是 HTML5 的 pushState API来修改浏览器的历史记录

     2.hashHistory 是通过改变地址后面的 hash(也就是URL中#后面的值) 来改变浏览器的历史记录。

        两种方式的特点

1.History API 提供了 pushState() 和 replaceState() 方法来增加或替换历史记录。

而 hash 没有相应的方法,所以browserHistory有替换历史记录的功能,hashHistory没有

2hashHistory实现简单,不需要做额外的服务端改造

2.Route组件

Route组件的Props对象中包含有path和component两个属性。根据当前URL和path属性的比对,Route组件配合其他的Route组件将包裹的子组件映射成完整的组件树

  •   path属性:URL的路径,且子Route的path将与父Route的path组合起来,例如:
<Route path='/' component={Father}>
    <Route path='son' component={Son}>
</Route>

包裹Son组件的Route和包裹Father的Route是父Route和子Route的关系,所以子Route对应的URL为'/'+'son'='/son'

  • path的路径匹配语法:

:paramName -->匹配一段位于 /? 或 # 之后的 URL

()-->匹配可选字段

* -->匹配任意字段

       <Route path="/hello/:name">         // 匹配 /hello/michael 和 /hello/ryan
       <Route path="/hello(/:name)">       // 匹配 /hello, /hello/michael 和 /hello/ryan
       <Route path="/files/*.*">           // 匹配 /files/hello.jpg 和 /file/path/to/hello.jpg
  • component属性:

当匹配到 URL 时,单个的组件会被渲染。它可以 被父 route 组件的 this.props.children 渲染。

  • Route组件将以下属性通过props注入component组件中

children属性:子Route所包裹的component

params属性:URL的动态字段

location:当前的location对象

router属性:一个对象,包含有与路由跳转有关的方法如push(url),repalce(url),go(n),goBack(),goForward()等等

(下文提及)

所以,Route包裹的组件可通过props.chidren,props.params的方式去引用这些属性

React-router的静态跳转和动态跳转

  • 静态跳转 --通过<Link>组件实现静态跳转(文章开头demo的代码)

import React from 'react';
import { Router, Route, browserHistory,Link} from 'react-router'
import ReactDOM from 'react-dom'; class App extends React.Component{ render(){ return (<div> <h1>导航</h1> <a href='/pageOne/:id'>通过a标签跳转到页面一</a> <br/> <Link to='/pageOne/:id'>通过Link组件跳转到页面一</Link> <br/> <Link to='/pageTwo/:id'>通过Link组件跳转到页面二</Link> {this.props.children} </div>) } } const PageOne = (props) => { return (<div> <h1>页面一</h1> </div>) } const PageTwo = (props) => { return (<div> <h1>页面二</h1> </div>) } ReactDOM.render( <Router history={browserHistory}> <Route path='/' component={App}> <Route path='pageOne/:id' component={PageOne}/> <Route path='pageTwo/:id' component={PageTwo} /> </Route> </Router>, document.getElementById('root') )

demo:


-------->


  • 动态跳转 --通过Route注入component中的route属性实现动态跳转

上面我们通过Link组件实现了路径的跳转,但这种方式也有一定的局限性。

第一,它是静态的,也就是必须以写入组件的方式实现跳转;

第二,它没办法提供"时光旅行"的功能,比如:跳到历史记录中的前一个界面,后一个界面,前N个界面,后N个界面,

等等

那么,我们能不能通过调用一个方法的方式去动态地实现路径跳转呢?上文提到的从Route组件中传入component中的

router属性对象解决了这个问题:

  • router.push('url') -->跳到URL为url的页面
  • router.goBack()   -->返回上一个页面
  • router.goForward() --> 去往历史记录中的下一个页面
  • router.go(n): -->n为正数表示向前跳跃,n为负数表示向后跳跃

下面我们基于第一个例子实现这样一个功能,当在从导航跳转到页面一的时候,通过点击按钮调用函数router.push('/')跳回初始的导航页面

import React from 'react';
import { Router, Route, browserHistory,Link} from 'react-router'
import ReactDOM from 'react-dom';
class App extends React.Component{
  render(){
    return (<div>
              <h1>导航</h1>
              <a href='/pageOne/:id'>通过a标签跳转到页面一</a>
              <br/>
              <Link to='/pageOne/:id'>通过Link组件跳转到页面一</Link>
              <br/>
             <Link to='/pageTwo/:id'>通过Link组件跳转到页面二</Link>
              {this.props.children}
            </div>)
  }
}
const PageOne = (props) => {
  console.log(props.router)
  return (<div>
            <h1>页面一</h1>
            <button onClick={() => {
              props.router.push('/')
            }} style={{backgroundColor:'red'}}>
                 跳转到导航页面
            </button>
          </div>)
}
const PageTwo = (props) => {
  return (<div>
            <h1>页面二</h1>
          </div>)
}
ReactDOM.render(
           <Router history={browserHistory}>
              <Route path='/' component={App}>
                  <Route path='pageOne/:id' component={PageOne}/>
                  <Route path='pageTwo/:id' component={PageTwo} />
              </Route>
            </Router>,
document.getElementById('root')
       )

demo如下:


     ---->


React-router官方英文文档地址:

https://github.com/ReactTraining/react-router/tree/v3/docs

React-router官方中文文档地址:

https://react-guide.github.io/react-router-cn/index.html

(注意!英文为Version3版本,与暂处于Version2的中文文档有一定差别,注意区分)

【react-router】从Link组件和a标签的区别说起,react-router如何实现导航并优化DOM性能?的更多相关文章

  1. [React Router v4] Use the React Router v4 Link Component for Navigation Between Routes

    If you’ve created several Routes within your application, you will also want to be able to navigate ...

  2. React和Vue的组件更新比较

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 24.0px "Helvetica Neue"; color: #404040 } p. ...

  3. 翻译 | 玩转 React 表单 —— 受控组件详解

    原文地址:React.js Forms: Controlled Components 原文作者:Loren Stewart 译者:小 B0Y 校对者:珂珂君 本文涵盖以下受控组件: 文本输入框 数字输 ...

  4. React中的通讯组件

    1.父传子:     传递:当子组件在父组件中当做标签使用的时候,给当前子组件绑定一个自定义属性,值为需要传递的数据     接收:在子组件内部通过this.props进行接收 2.子传父     传 ...

  5. reactjs-swiper react轮播图组件基于swiper

    react轮播图组件基于swiper demo地址:http://reactjs-ui.github.io/reactjs-swiper/simple.html 1. 下载安装 npm install ...

  6. 我们一起来详细的了解react的语法以及组件的使用方法

    jsx的介绍 React 使用 JSX 来替代常规的 JavaScript. JSX 是一个看起来很像 XML 的 JavaScript 语法扩展. jsx的优点 JSX 执行更快,因为它在编译为 J ...

  7. Vue之单文件组件的数据传递,axios请求数据及路由router

    1.传递数据 例如,我们希望把父组件的数据传递给子组件. 可以通过props属性来进行传递. 传递数据三个步骤: 步骤1:在父组件中,调用子组件的组名处,使用属性值的方式往下传递数据 <Menu ...

  8. React Native 学习-组件说明和生命周期

    组件的详细说明(Component Specifications) 当通过调用 React.createClass() 来创建组件的时候,你应该提供一个包含 render 方法的对象,并且也可以包含其 ...

  9. React:快速上手(2)——组件通信

    React:快速上手(2)——组件通信 向父组件传递数据 父组件可以通过设置子组件的props属性进行向子组件传值,同时也可以传递一个回调函数,来获取到子组件内部的数据. 效果演示 子组件是输入框,父 ...

随机推荐

  1. 为什么亚马逊云计算中的DNS服务叫Route53?

    最近在用亚马逊的云计算服务,看到它的DNS服务的名字叫做"Route 53".这个名字让我很好奇,为什么叫"Route 53"呢?有什么特殊含义? 看到了这个Q ...

  2. 转:微信开发获取地理位置实例(java,非常详细,附工程源码)

    微信开发获取地理位置实例(java,非常详细,附工程源码)   在本篇博客之前,博主已经写了4篇关于微信相关文章,其中三篇是本文基础: 1.微信开发之入门教程,该文章详细讲解了企业号体验号免费申请与一 ...

  3. GAME(A)性能测试过程模型

  4. H5常见的兼容问题及解决

    最近这两天经常遇到一些麻烦的兼容问题,统一整理一下,比较简单也不是特别全面,希望大家多多交流. 几种IE6 bug的解决方法 1)png24位的图片在iE6浏览器上出现背景,解决方案是做成PNG8.也 ...

  5. Bootstrap记录

    左侧 导航下拉: <li class="dropdown"> <a href="#" class="dropdown-toggle& ...

  6. Codeforces Good Bye 2016 题解

    好久没有fst题了...比赛先A了前4题然后发现room里有人已经X完题了没办法只能去打E题,结果差一点点打完...然后C题fst掉了结果就掉rating 了...下面放题解 ### [A. New ...

  7. 2017-2-20 C#基础 运算符

    C#的运算符主要分五种:算数运算符,关系运算符,逻辑运算符,条件运算符,赋值运算符.算术运算符有 + - * /  %    ++    --;关系运算符有    ==    !=    >   ...

  8. jwplayer 限制拖动事件 快进 快退

    开源精神不是ctrl +c    +   ctrl+v  谢谢 最近项目需要视频播放不能拖动,我已经实现即不能向前拖动,也不能向后拖动, 方法:打开用记事本 或者notepad  工具打开 jwpla ...

  9. 关于Storm Stream grouping

    在Storm中, 开发者可以为上游spout/bolt发射出的tuples指定下游bolt的哪个/哪些task(s)来处理该tuples.这种指定在storm中叫做对stream的分组,即stream ...

  10. linux中添加环境变量(python为例)

    最近想用Django搭建个人博客,之前学了些python基础语法,准备边学习Django边实战操作.自己有一个阿里云服务器,用的centOS,自带的是python2.7版本,我直接安装了python3 ...