(注:参考自官方英文文档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. 访问量分类统计(QQ,微信,微博,网页,网站APP,其他)

    刚准备敲键盘,突然想起今天已经星期五了,有点小兴奋,一周又这么愉快的结束,又可以休息了,等等..我好像是来写Java博客的,怎么变成了写日记,好吧,言归正传. 不知道大家有没有遇到过这样的需求:统计一 ...

  2. 模块化写法-IIFE解析

    一.IIFE解释 全拼Imdiately Invoked Function Expression,立即执行的函数表达式.  像如下的代码所示,就是一个匿名立即执行函数: (function(windo ...

  3. [Bullet3]三种碰撞检测及实现

    官方文档:http://bulletphysics.org 开源代码:https://github.com/bulletphysics/bullet3/releases API文档:http://bu ...

  4. winsshfs的快速入手

    之前在公司使用mac ,并且通过mac下的osfuse和sshfs连接,直接将虚拟机的文件目录同步到了本地,并且可以进行实时操作修改,对于写项目,确实是省了很大一部分上传的精力. 于是在自己的win下 ...

  5. node将excel内容转json

    小颖分享的这个方法,前提是你已经安装了node,如果大家不知道自己是否安装过node可以打开cmd,然后执行:node -v,如果安装过,你会看到你安装的node版本号,如果没有安装请先安装node. ...

  6. DP 动态规划

    p1269 马棚 题目: 每天,小明和他的马外出,然后他们一边跑一边玩耍.当他们结束的时候,必须带所有的马返回马棚,小明有K个马棚.他把他的马排成一排然后跟随它走向马棚,因为他们非常疲劳,小明不想让他 ...

  7. 第23篇 js快速学习知识

    前面说了js的一些高级方面的基础知识,这些都是比较容易出错的和比较难理解的东西,除了这些之外其它的知识都比较简单了,基础学好了,扩展起来就是小意思.今天说说js方面可以快速学习和入门的知识. 1.闭包 ...

  8. webpack 引用 jquery + bootstrap 报错解决

    webpack 引用 jquery + bootstrap , error : jQuery is not defind 在webpack.dev.conf.js plugins[] 加入 new w ...

  9. Asp.Net 常用工具类之Office—Excel导出(4)

    开发过程中各类报表导入导出防不胜防,网上也是各种解决方法层出不穷,比如Excel,CSV,Word,PDF,HTML等等... 网上各种导出插件也是层出不穷,NPOI,微软Microsoft.Offi ...

  10. JNI只C性能测试

    深入学习JNI之前,介绍一个比较好的学习文档:jni详细教程.我这里只是一个Demo测试性能,至于入门教程请看我前一篇博文. Demo展示 这个Demo用于从小到大的冒泡排序,App.java代码: ...