操纵历史,利用HTML5 History API实现无刷新跳转
杰拉斯 | 时间:2012-09-05, Wed | 65,948 views前端开发
写在前面
有一次在上点点网的时候,发现登陆、注册动画效果非常华丽,但让我感到震惊的是页面竟能够实现无刷新跳转(已改版,观看此效果可以猛击此处:GitHub或阅FM),回顾了所学的前端知识,似乎没有任何技术可以实现这一点,于是百度搜罗了一下,才发现这原来是使用HTML5中History API实现的效果,但奈何一直未曾派上用场。直到博客改版时,才将这一技术应用起来。
HTML4中的History API
history这个东西大家应该都不陌生,我们经常使用history.back(-1)来实现后退功能,具体的属性和方法如下:
属性
- length 历史的项数。JavaScript 所能管到的历史被限制在用浏览器的“前进”“后退”键可以去到的范围。本属性返回的是“前进”和“后退”两个按键之下包含的地址数的和。
方法
- back() 后退,跟按下“后退”键是等效的。
- forward() 前进,跟按下“前进”键是等效的。
- go() 用法:history.go(x);在历史的范围内去到指定的一个地址。如果 x < 0,则后退 x 个地址,如果 x > 0,则前进 x 个地址,如果 x == 0,则刷新现在打开的网页。history.go(0) 跟 location.reload() 是等效的。
HTML5中的History API
- history.pushState(data, title [, url]):往历史记录堆栈顶部添加一条记录;data会在onpopstate事件触发时作为参数传递过去;title为页面标题,当前所有浏览器都会忽略此参数;url为页面地址,可选,缺省为当前页地址。
- history.replaceState(data, title [, url]) :更改当前的历史记录,参数同上。
- 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的代码:
function supports_history_api(){ return !!(window.history && history.pushState); }
为什么要使用History API
在AJAX给我们带来提高用户体验、减少HTTP连接数等好处的同时,也渐渐显露出一些不足之处,比如:
- 无法使用浏览器的前进、后退来切换前后数据。
- 当我们将浏览器地址栏中的链接与朋友分享时,可能实际上却并非我们期望的内容。
- 单纯地使用AJAX不利于搜索引擎优化。
实现无刷新跳转
上面都是一些理论知识(部分整理于网上),那么无刷新跳转要怎么实现呢?很简单的一句代码:
history.pushState(null, '', 'newpage.html');
如果你使用的是HTML5浏览器,并点击了上面的按钮,那么应该可以看到,地址栏的地址发生了改变,页面却没有刷新或跳转。
这是一个最简单的Demo,虽然实现了地址的无刷新跳转,但内容却没有对应改变,我们只要在pushState的同时配合上AJAX,一个无刷新的页面跳转效果便完成了,AJAX的实现与本文主题无关,这里就不再赘述,下面给出的Demo下载会有AJAX部分的代码。
兼容浏览器前进后退效果
简单地利用history.pushState,虽然可以实现无刷新地址跳转,但并没有解决在浏览器中前进后退,内容并没有相应改变这个问题,此时就需要用到window.onpopstate事件了,当页面地址发生改变时,便会触发window对象的onpopstate事件,而我们只要在pushState的同时将当前页面的参数传递给浏览器,并在onpopstate事件中作出相应便可以了:
history.pushState({title: '页面标题', html: '页面HTML'}, '', 'newpage.html'); window.onpopstate = function(event){ if(event && event.state){ document.title = event.state.title; document.body.innerHTML = event.state.html; } }
当然,还有许多需要考虑的因素,如当页面打开时event.state为空,最后一次后退会失效等等,这就需要在页面载入时先将当前的标题与HTML保存到变量中,并在当event.state为空时将变量中的内容显示出来。
还有考虑当链接中含有井号“#”时应如何处理等等……
无刷新跳转的具体实现
熬夜将博文写出,顺便将Demo写成了一个jQuery插件,精神比较差,基本的功能已经实现,一些细节就暂不考虑了,如果有什么问题欢迎大家提出。
话说这次的博文也写的比较语无伦次,还请大家见谅。。
下载地址:http://vdisk.weibo.com/s/J2Ckb
注:由于History API存在安全方面的限制,请在服务端运行方能看到效果
如需转载请注明出处:杰拉斯的博客
无刷新,直接用ajax就好了啊,何必折腾着用HTML5呢,HTML5吵得火,但是离实际运用还有很长的路要走!
的确是利用AJAX来实现的呀,HTML5是为了同时将页面地址跳转。
使用搞基浏览器看地址栏。这种实体页面和ajax配合方式作出来的页面 既有交互体验又有seo
下载链接失效了
不会吧,微盘的呀?
博主,地址真得失效咯~
已经重新上传了一份。
[...]转载出处:蓝飞技术部落格[...]
[...]转载出处:蓝飞技术部落格[...]
"无刷新跳转",这个技术会用在什么场景呢?
站长刚下载了在谷歌Chrome无法实现,请看下代码
唉,为什么每次评论都被定性为垃圾内容啊,继续博主帮助啊,55555555
@有一份田
会么?
不会,正在研究,略蛋疼.....
[...]转载出处:蓝飞技术部落格[...]
这个不错,可以使用的。
为什么非要封jq插件呢 ,js不行么 ,并不是所有的都用的jq框架 我不用jq就没法用了
收下我的膝盖
能不能做成花瓣网列表页那种效果呢?页面和数据都变了但前一页的Dom还在?
可以实现,但这已经是跟 History API 无关的业务啦
[...]操纵历史,利用HTML5 History API实现无刷新跳转[...]
[...]操纵历史,利用HTML5 History API实现无刷新跳转 蓝飞[...]
[...]这样在用户点击前进后退时也可以很好的监听url,来做相应的页面渲染。若用户刷新了页面,但没有相应的页面资源,这时页面就会显示不存在。所以我认为较好的方法是在写pushState()第三个参数的时候,写为?a=1这样的参数形式。History.js 也是这么写的。但是这样应该会多一次请求。也许使用 nodeJS 作为中间层会好一些吧。对于上述的探索,不知道是不是我还不够深入,总觉得还是不够完美。参考[...]
[...]这样在用户点击前进后退时也可以很好的监听url,来做相应的页面渲染。若用户刷新了页面,但没有相应的页面资源,这时页面就会显示不存在。所以我认为较好的方法是在写pushState()第三个参数的时候,写为?a=1这样的参数形式。History.js 也是这么写的。但是这样应该会多一次请求。也许使用 nodeJS 作为中间层会好一些吧。对于上述的探索,不知道是不是我还不够深入,总觉得还是不够完美。参考[...]
[...]这样在用户点击前进后退时也可以很好的监听url,来做相应的页面渲染。若用户刷新了页面,但没有相应的页面资源,这时页面就会显示不存在。所以我认为较好的方法是在写pushState()第三个参数的时候,写为?a=1这样的参数形式。History.js 也是这么写的。但是这样应该会多一次请求。也许使用 nodeJS 作为中间层会好一些吧。对于上述的探索,不知道是不是我还不够深入,总觉得还是不够完美。参考[...]
[...]这样在用户点击前进后退时也可以很好的监听url,来做相应的页面渲染。若用户刷新了页面,但没有相应的页面资源,这时页面就会显示不存在。所以我认为较好的方法是在写pushState()第三个参数的时候,写为?a=1这样的参数形式。History.js 也是这么写的。但是这样应该会多一次请求。也许使用 nodeJS 作为中间层会好一些吧。对于上述的探索,不知道是不是我还不够深入,总觉得还是不够完美。参考[...]
[...]操纵历史,利用HTML5 History API实现无刷新跳转 蓝飞[...]
[...]操纵历史,利用HTML5 History API实现无刷新跳转 蓝飞[...]