在学习React Router时,看到有关History有以下描述:html
React Router 是创建在 history 之上的。 简而言之,一个 history 知道如何去监听浏览器地址栏的变化, 并解析这个 URL 转化为 location 对象, 而后 router 使用它匹配到路由,最后正确地渲染对应的组件。
这段描述看的晕晕的,history究竟是个什么东西呢?这得从history API的出身提及。前端
咱们都知道一个URL表明了网络上惟一的一个资源。这个资源能够是一个页面,一张图片等等。在地址栏里输入一个url地址,浏览器就会将对应的资源展现出来。当在不一样的地址之间跳转时,咱们很天然地想要回退或者前进一个地址。为了实现这个功能,浏览器厂商定义了history
对象。这时的history
对象大体有go()
、forward()
、back()
等方法,用于实现历史记录的访问、跳转。html5
使用 history API与浏览器历史记录进行交互
history
与 URL 就这样和谐的相处了一段时间,直到ajax技术的兴起。git
浏览器有一个限制:若是你改变了URL,甚至是经过脚本,它就得向服务器发送请求,刷新整个页面。这很耗时,也耗资源,由于有时候2个页面长得差很少,仅仅有一小块地方不一样。为了解决这个问题,ajax
技术兴起,利用ajax,能够不改变URL,只向服务器请求须要变更的数据,而后在前端经过DOM操做实现页面的局部更新。github
ajax
极大提升了页面加载速度与用户体验。不过它同时带来了一个问题:同一个URL地址,可能会展现不少不一样的信息,那么它做为惟一资源标识符的这个定义,在这里被破坏了。ajax
有没有一个一箭双鵰的办法呢?既能够实现页面的局部更新,又可以改变地址栏里的URL?浏览器
第一个跳出来解决问题的是URL中的#
。#
表明网页中的一个位置。它右边的字符就是页面中的位置标识符。例以下面的URL:服务器
http://www.example.com/index.html#print
就表明网页index.html的print位置。浏览器读取这个URL后,会自动将print位置滚动至对应的区域。为网页位置指定标识符,有两个方法。一是使用锚点,好比,二是使用id属性,好比<div id="print" >网络
#
的威力在于它是用来指导浏览器动做的,对服务器端彻底无用。因此,HTTP请求中不包括#
,改变#
不触发网页重载。所以,若是咱们在使用ajax局部刷新页面时,同时改变URL#
后面的标识符,就实现了局部刷新+改变URL了。学习
事实上,早前的twitter、google就是这么实现的。google甚至为此专门定义了一个搜索引擎优化的标识符#!
。能够参考这篇文章:URL的井号
URL毕竟是用于资源分享的,带个#
总感受有点别扭。若是不用#
,有没有办法可以修改URL,同时又不向服务器发送请求呢?这就轮到history对象再次登场了。在HTML5规范中,W3C对history对象进行了一波升级:
HTML5 history API包括2个方法:history.pushState()和history.replaceState(),以及1个事件:window.onpopstate。
利用这2个方法,能够实现经过脚本修改浏览器中的URL地址,而不触发页面重载。采用这个方案,一个ajax请求过程是这样的:
问题获得解决。
在React Router中,将上述2个方案进行了整合,统一到了一个history库中。也就是咱们看到的HashHistory
和BrowserHistory
。HashHistory
是上面井号方案的封装,BrowserHistory
则是对History方案的封装。特别须要注意到是,BrowserHistory须要对服务器端改造。
为何?
考虑如下场景,咱们用React Router的BrowserHistory开发了一个单页面应用,主页地址以下:
http://www.mysite.com/index
在index中能够点击连接进入欢迎页,详细介绍页等,地址为:
http://www.mysite.com/index/welcome http://www.mysite.com/index/detail
若是咱们在浏览器里直接输入主页面地址,而后经过页面里连接跳转到二级页面,通常是没有问题的。可是,若是在浏览器里直接输入http://www.mysite.com/index/welcome
会发生什么呢?
浏览器会认为这是一个URL请求,向服务器端请求这个URL表明的资源。但咱们这是一个单页面应用,服务端只有一个index.html页面,没有跟这个地址匹配的资源,页面就会报错了。
所以,咱们须要稍微改造一下服务端,将全部这样的请求都指向index.html页面,由前台处理路由信息。
#
有话说:
为嘛,长得丑就要被淘汰吗!