HTML5 history API,制造更好的阅读体验

HTML5 history API有什么用呢?

从Ajax翻页的题目提及

请设想你正在看一个视频下面的批评,在翻到十几页的时刻,你发明一个写得稍长,但异常风趣的批评。合理你想要停下滚轮细看的时刻,手残按到了F5。然后,页面革新了,批评又回到了第一页,所以你又要从新翻一次。

再或许,你想把这个批评发给他人分享,一面给了他人页面地点(为何不直接复制呢?由于要连带视频等场景啊),一面又要加一句吩咐:请翻到下面批评的第XX页的XX楼。

这就是题目。试想一下,假如浏览器能记着你当前的状态(比方看到了第十几页),而不是一革新就复原,是不是是就显得智能多了?

为何用Ajax?

用Ajax完成翻页等内容切换是有缘由的。在传统的无Ajax的站点里,页面A和页面B能够只需10%的处所是差别的,其他90%的内容(特别是导航、页脚等公用元素)都是一样的,但却依然须要浏览器下载并显现新的一全部页面。而假如运用Ajax,不仅节省了浏览器须要下载的资本,而且无革新切换显著比页面跳转更腻滑、流通。

就视频下面的批评来讲,Ajax能够说是必需的。视频如许的重量级元素,动不动给你从新加载一次,不能忍。

传统的跳转翻页的可取之处

传统的不运用Ajax的站点,每个翻页是一个跳转,然后你能够在浏览器地点栏里看到诸如?page=2如许的参数。每一页就如许经由过程地点栏的URL做了标记,每一次要求,浏览器都邑依据参数返回准确的页码。

所以,传统的跳转翻页,革新也不会丧失状态。

连系二者

如今我们就能够想到,假如在Ajax更新页面部份内容的同时,也在地点栏的URL里更新状态参数,就能够做出更圆满的Ajax翻页了。

不过,JavaScript修正location的除hash外的恣意属性,页面都邑以新URL从新加载。而唯一不引发革新的hash参数并不会发送到服务器,因而服务器没法获得状态。

然后,HTML5 history API将处置惩罚这个题目。

引见HTML5 history API

HTML5 history API只包括2个要领:history.pushState()history.replaceState(),以及1个事宜:window.onpopstate

history.pushState()

它的完全部是 history.pushState(stateObject, title, url),包括三个参数。

第1个参数是状态对象,它能够理解为一个拿来存储自定义数据的元素。它和同时作为参数的url会关联在一同。

第2个参数是题目,是一个字符串,现在各种浏览器都邑疏忽它(今后才有能够启用,用作页面题目),所以设置成什么都没关联。现在发起设置为空字符串。

第3个参数是URL地点,平常会是简朴的?page=2如许的参数作风的相对路径,它会自动以当前URL为基准。须要注重的是,本参数URL须要和当前页面URL同源,否则会抛出毛病。

挪用pushState()要领将新天生一条历史纪录,轻易用浏览器的“退却”和“行进”来导航(“退却”然则相称经常使用的按钮)。别的,从URL的同源战略能够看出,HTML5 history API的起点是很明白的,就是让无跳转的单站点也能够将它的各个状态保留为浏览器的多条历史纪录。当经由过程历史纪录从新加载站点时,站点能够直接加载到对应的状态。

history.replaceState()

它和history.pushState()要领基本雷同,区分只需一点,history.replaceState()不会新天生历史纪录,而是将当前历史纪录替换掉

window.onpopstate

push的对峙就是pop,能够猜到这个事宜是在浏览器掏出历史纪录并加载时触发的。但实际上,它的前提是比较刻薄的,险些只需点击浏览器的“行进”、“退却”这些导航按钮,或许是由JavaScript挪用的history.back()等导航要领,且切换前后的两条历史纪录都属于统一个网页文档,才会触发本事宜。

上面的“统一个网页文档”请理解为JavaScript环境的document是统一个,而不是指基本URL(去掉各种参数的)雷同。也就是说,只需有从新加载发作(无论是跳转到一个新站点照样继承在本站点),JavaScript全局环境发作了变化,popstate事宜都不会触发。

popstate事宜是设想出来和前面的2个要领搭配运用的。平常只需在经由过程前面2个要领设置了统一站点的多条历史纪录,并在其之间导航(行进或退却)时,才会触发这个事宜。同时,前面2个要领所设置的状态对象(第1个参数),也会在这个时刻经由过程事宜的event.state返还返来。

另外请注重,history.pushState()history.replaceState()自身挪用时是不触发popstate事宜的。pop和push毕竟不一样!

怎样运用

HTML5 history API的内容不多,详细怎样运用它来革新Ajax翻页呢?

起首,在服务器端增加对URL状态参数的支撑,比方?page=3将会输出对应页码的内容(后端模板)。也能够是服务器端把对应页码的数据给JavaScript,由JavaScript向页面写入内容(前端模板)。

接下来,运用history.pushState(),在任一次翻页的同时,也设置准确的带参数的URL。代码多是如许:

newURL = "?page=" + pageNow;
history.pushState(null, "", newURL);

到此,就处置惩罚了F5革新状态复原的事了。

不过,还没有完毕,在浏览器中点击退却,比方从?page=3退到?page=2,会发明没有变化。按道理说,这时刻也应当对应变化。这就要用到popstate事宜了。

window增加popstate事宜,到场这类导航变化时的处置惩罚。代码多是如许(jQuery):

$(window).on("popstate", function(event) {

    // 获得之前经由过程pushState保留的state object,只管本示例并不盘算运用它。
    // jQuery对event做了一层包装,须要经由过程originalEvent获得原生event。
    var state = event.originalEvent.state,

        // 本示例直接取URL参数来处置惩罚
        reg = /page=(\d+)/,
        regMatch = reg.exec(location.search),

        // 第1页的时刻既能够是 ?page=1,也能够基础没有page参数
        pageNow = regMatch === null ? 1 : +regMatch[1];

    updateByPage(pageNow);
});

如许,就完成了。如许看起来是不是会以为还挺轻易的呢?在支撑HTML5 history API的浏览器中,以上部份就已做到了带页码纪录的Ajax翻页。

有待推敲的兼容性题目

依据[caniuse][]上的数据,IE10+及其他主流浏览器都支撑HTML5 history API。为保证不支撑的浏览器不报错,能够到场是不是支撑HTML5 history API的推断:

// 参考自 http://modernizr.com/download/#-history 源码
var isHistoryApi = !!(window.history && history.pushState);

// ...

if(isHistoryApi){
    // ...
}

如许,一个Ajax翻页,在支撑HTML5 history API的浏览器上,将会智能地保留当前页码信息,而不支撑的浏览器依然能够一般运用,只是不保留页码信息(就像革新前那样)。我以为,根据“渐进加强”的思绪,如许就是最好的了,也就是:只运用较少的代码优化高等浏览器的运用体验。

假如真的想要在各种浏览器里都表现一致,具有如许的纪录功用呢?

这时刻引荐运用Benjamin Lupton的[History.js][],它供应和HTML5 history API近似的api,会在不支撑的浏览器里回退到hash情势去处置惩罚历史纪录。只管为了兼容这类hash的回退情势你能够要分外做点事(hash不会发送到服务器端),但它确切能够让你做到更广局限的兼容。

HTML5 history API并不圆满

纵然只斟酌支撑HTML5 history API的浏览器,它们对HTML5 history API的一些细节处置惩罚也会有差别和题目。History.js供应的只针对HTML5浏览器的版本,依然包括了不少处置惩罚兼容题目的代码。

然则,不圆满也没有关联。以我的测试效果,本文所引见的简朴的写法,就能够在绝大部份支撑HTML5 history API的浏览器上一般运转。假如你忧郁有哪些浏览器会有潜伏题目,去测试谁人浏览器就能够了。你末了用于兼容处置惩罚的自写代码极能够远比一个JavaScript库少很多,毕竟,你也不一定会喜好分外引入一个JavaScript库来完成一个功用吧。

一些相关内容

地点栏里的hash曾是过去被普遍用来纪录页面状态的标记,你能够浏览[W3C Blog的这篇文章][]相识它的阅历。

如今能够在不革新的状态下操纵浏览器地点栏和历史纪录了,那统一站点的一般链接跳转是不是都能够转变为Ajax来提拔运用体验?是的,而且已有了pjax[]这些特地完成这个功用的作品。

不只是翻页,HTML5 history API将特别适宜用在大批运用Ajax、包括多个视图的单页运用。

为一个页面的每个状态都天生一条历史纪录不一定适宜(会让用户的历史纪录变多变乱),酌情运用replaceState()而不是pushState()来掌握历史纪录的数目。

结语

HTML5 history API简朴易学,不多的几行代码就能够做到“状态纪录”这个小小的革新,假如能够由你挑选“渐进加强”,它还真的能够上线!

(从新编辑自我的博客,原文地点:http://acgtofe.com/posts/2014/12/play-with-browser-history

    原文作者:EdwardUp
    原文地址: https://segmentfault.com/a/1190000002447556
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞