当前位置: 代码迷 >> HTML/CSS >> 操纵历史,利用HTML5 History API兑现无刷新跳转
  详细解决方案

操纵历史,利用HTML5 History API兑现无刷新跳转

热度:835   发布时间:2012-09-08 10:48:07.0
操纵历史,利用HTML5 History API实现无刷新跳转

写在前面

有一次在上点点网的时候,发现登陆、注册动画效果非常华丽,但让我感到震惊的是页面竟能够实现无刷新跳转(已改版,观看此效果可以猛击此处:GitHub阅FM),回顾了所学的前端知识,似乎没有任何技术可以实现这一点,于是百度搜罗了一下,才发现这原来是使用HTML5中History API实现的效果,但奈何一直未曾派上用场。直到博客改版时,才将这一技术应用起来。


HTML4中的History API

history这个东西大家应该都不陌生,我们经常使用history.back(-1)来实现后退功能,具体的属性和方法如下:

属性

  1. length 历史的项数。JavaScript 所能管到的历史被限制在用浏览器的“前进”“后退”键可以去到的范围。本属性返回的是“前进”和“后退”两个按键之下包含的地址数的和。

方法

  1. back() 后退,跟按下“后退”键是等效的。
  2. forward() 前进,跟按下“前进”键是等效的。
  3. go() 用法:history.go(x);在历史的范围内去到指定的一个地址。如果 x < 0,则后退 x 个地址,如果 x > 0,则前进 x 个地址,如果 x == 0,则刷新现在打开的网页。history.go(0) 跟 location.reload() 是等效的。

HTML5中的History API

  1. history.pushState(data, title [, url]):往历史记录堆栈顶部添加一条记录;data会在onpopstate事件触发时作为参数传递过去;title为页面标题,当前所有浏览器都会忽略此参数;url为页面地址,可选,缺省为当前页地址。
  2. history.replaceState(data, title [, url]) :更改当前的历史记录,参数同上。
  3. history.state:用于存储以上方法的data数据,不同浏览器的读写权限不一样。

浏览器兼容性

API Chrome Firefox(Geko) Internet Explorer Opera Safari
pushState, replaceState 5 4.0(2.0) -- 11.50 5.0
history.state -- 4.0(2.0) -- 11.50 --
下面是一段检测浏览器是否支持History API的代码:
  1. function supports_history_api(){
  2.         return !!(window.history && history.pushState);
  3. }


为什么要使用History API

在AJAX给我们带来提高用户体验、减少HTTP连接数等好处的同时,也渐渐显露出一些不足之处,比如:
  1. 无法使用浏览器的前进、后退来切换前后数据。
  2. 当我们将浏览器地址栏中的链接与朋友分享时,可能实际上却并非我们期望的内容。
  3. 单纯地使用AJAX不利于搜索引擎优化。


实现无刷新跳转

上面都是一些理论知识(部分整理于网上),那么无刷新跳转要怎么实现呢?很简单的一句代码:
  1. history.pushState(null, '', 'newpage.html');
点此查看效果
如果你使用的是HTML5浏览器,并点击了上面的按钮,那么应该可以看到,地址栏的地址发生了改变,页面却没有刷新或跳转。

这是一个最简单的Demo,虽然实现了地址的无刷新跳转,但内容却没有对应改变,我们只要在pushState的同时配合上AJAX,一个无刷新的页面跳转效果便完成了,AJAX的实现与本文主题无关,这里就不再赘述,下面给出的Demo下载会有AJAX部分的代码。


兼容浏览器前进后退效果

简单地利用history.pushState,虽然可以实现无刷新地址跳转,但并没有解决在浏览器中前进后退,内容并没有相应改变这个问题,此时就需要用到window.onpopstate事件了,当页面地址发生改变时,便会触发window对象的onpopstate事件,而我们只要在pushState的同时将当前页面的参数传递给浏览器,并在onpopstate事件中作出相应便可以了:
  1. history.pushState({title: '页面标题', html: '页面HTML'}, '', 'newpage.html');
  2. window.onpopstate = function(event){
  3.         if(event && event.state){
  4.                 document.title = event.state.title;
  5.                 document.body.innerHTML = event.state.html;
  6.         }
  7. }
当然,还有许多需要考虑的因素,如当页面打开时event.state为空,最后一次后退会失效等等,这就需要在页面载入时先将当前的标题与HTML保存到变量中,并在当event.state为空时将变量中的内容显示出来。

还有考虑当链接中含有井号“#”时应如何处理等等……


无刷新跳转的具体实现

熬夜将博文写出,顺便将Demo写成了一个jQuery插件,精神比较差,基本的功能已经实现,一些细节就暂不考虑了,如果有什么问题欢迎大家提出。

话说这次的博文也写的比较语无伦次,还请大家见谅。。

下载地址:http://vdisk.weibo.com/s/bR64T


还有话说

如果您愿意支持一下的话,欢迎戳一戳我的博客→http://www.clanfei.com

由于前段时间博客大规模改版,再加上购置了一级域名,现阶段访问量比较惨淡ToT。。如蒙关照,不胜感激。。



=======================签 名 档=======================

原文地址(我的博客):http://www.clanfei.com/2012/09/1646.html
欢迎访问交流,至于我为什么要多弄一个博客,因为我热爱前端,热爱网页,我更希望有一个更加自由、真正属于我自己的小站,或许并不是那么有名气,但至少能够让我为了它而加倍努力。。
=======================签 名 档=======================




1楼sbwwkmyd昨天 11:13
看看这个http://www.51nod.com/today.html#!type=,不需要html5支持。
Re: CooLanfei昨天 18:31
回复sbwwkmydn它是利用井号“#”来跳转的,并不是真正的地址跳转,实际上还是在同一个页面上。
Re: sbwwkmyd昨天 18:48
回复CooLanfein另外一点,页面恢复不仅仅是innerHTML这么简单。因为还有脚本及其绑定。
Re: CooLanfei昨天 18:51
回复sbwwkmydn的确,脚本跟CSS都是必须要考虑的问题。n上面的Demo只是实现了最基础的功能,一些细节方面还没有考虑。
Re: sbwwkmyd昨天 18:58
回复CooLanfein完全满足你的“为什么要使用History API”三点要求
Re: CooLanfei昨天 19:13
回复sbwwkmydn他的链接的href属性都是带井号的,这对第三点似乎不太好吧?n先上课去了,回来再共同探讨~
Re: sbwwkmyd昨天 19:15
回复CooLanfein那是因为你是用浏览器访问的,如果你模拟搜索引擎,会得到不一样的href,另外#!是可以被google识别的。
Re: CooLanfei昨天 19:17
回复sbwwkmydn这个我倒没试过,不过这样的话还需要后台配合。n#!可以被谷歌识别这个我还真不清楚,受教了!
Re: CooLanfei昨天 19:17
回复sbwwkmydn他的链接的href属性都是带井号的,这对第三点似乎不太好吧?n 先上课去了,回来再共同探讨~
Re: sbwwkmyd昨天 19:22
回复CooLanfein那你试试http://www.51nod.com/today.html?type=hot与http://www.51nod.com/today.html#type=hot或者nhttp://www.51nod.com/today.html#!type=hot
Re: CooLanfei昨天 19:23
回复sbwwkmydn内容一样,但都是通过AJAX来获取的,并不是真正页面本身的内容。
Re: sbwwkmyd昨天 23:24
回复CooLanfein所以才能同时拥有ajax的优势啊。
Re: CooLanfei9小时前
回复sbwwkmydn刚忙完。。有点晚= =。。我思考了下,总结了几点:n一、井号方式可以兼容HTML4浏览器,History API无法做到,这是硬伤。n二、在不支持js的浏览器或一些移动浏览器中上面提到的网站就有异常了,History API虽然在HTML4浏览器中无效,但在任何浏览器中均能正常浏览。n三、井号的方式虽然同样可以实现跳转,但还需要后台的配合,History API不需要后台的配合便可以实现,降低了前端后台的耦合度。n四、井号链接还有一个很重要的功能,就是实现页面位置的跳转,如果井号用作它用,原有的功能就失效了。n五、个人认为一种新技术的出现必然有它的道理,利用井号可以算是一种HTML4中为了实现类似的功能的hack而已,如果有办法直接实现的事情何不采用简单的办法来做呢?nn个人观点,欢迎探讨。