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

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

http://www.cnblogs.com/penghuwan/p/6623099.html?utm_source=tuicool&utm_medium=referral

对比<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的中文文档有一定差别,注意区分)

发布了145 篇原创文章 · 获赞 1552 · 访问量 796万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 猿与汪的秘密 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览