HTML5:History API

lqadam 2011-11-21

大家在浏览Facebook的相册时有没有发现,页面局部刷新的同时地址栏的地址也改变了,而且不是hash的方式。它使用的就是HTML5 history新增的几个API,作为window的一个全局变量,在HTML4的时代history已不是什么新鲜的事物了。我们经常使用的就有history.back()以及history.go() 。

下面我们来了解下history都有哪些改变。

1. HTML4时代的history API

A)history.length:当前历史列表中的历史记录数(我大概测了下,IE6+是从0开始的,其他的是从1开始的,若有误请反馈哈,^_^);

B)history.go(n):前进或后退n条记录,当n=0或空时会刷新当前页;

C)history.back():后退一步;

D) history.forward():前进一步;

2.HTML5新增的API

A)history.pushState(data,title[,url]):往历史记录堆栈顶部添加一条记录;data会在onpopstate事件触发时作为参数传递过去;title为页面标题,当前所有浏览器都会忽略此参数;url为页面地址,可选,缺省为当前页地址;

B)history.replaceState(data,title[,url]):更改当前的历史记录,参数同上;

C)history.state:用于存储以上方法的data数据,不同浏览器的读写权限不一样;

D)window.onpopstate:响应pushState或replaceState的调用;

有了这几个新的API,针对支持的浏览器,我们可以构建用户体验更好的应用了。就像刚提到的Facebook相册,虽然是AJAX的方式,但用户可以直接复制页面地址分享给好友,好友打开看到的就是AJAX加载的数据,做到了书签化。当然这里面需要做的工作远不是说的这么简单。

3.浏览器的兼容性&检测

在HTML5支持不一的时代,新的API总会存在或这或那的兼容性问题。因此我们有必要了解新接口在不同浏览器下的兼容性。

截图来自:《Manipulatingthebrowserhistory》

如何检测浏览器是否支持HistoryAPI?

function supports_history_api() {
    return !!(window.history && history.pushState);
}

 

如何检测history.state的兼容性呢?我尝试赋值history.state=1,但history.state在不同浏览器下的读写权限不一样,所以我们换种方式:

var originalHistoryState = history.state;  // 保存原有的历史信息
history.replaceState(1, null);  // 替换当前历史信息
var stateSupport = history.state == 1;  // 是否存储到刚设置的历史信息
history.replaceState(originalHistoryState, null); // 恢复原来的历史信息

 

4.安全性

我们看一个例子:DEMO页面在tenpay.com的域名下,用户点击“付款”链接尝试加载另一个域名的某张图片。

可以看到,当我们尝试改变当前地址为一个协议不同、(子)域名不同的地址时,会触发相应的错误。新API在安全性方面作了考虑,所以还是安全的。

5.AJAXBookmark–AJAX书签化

有了新API的支持,我们可以针对不同浏览器作一些差异化的用户体验。尤其是在AJAX盛行的年代,无历史记录已经是一大诟病。

为了解决AJAX的书签化问题,我们需要解决的主要是以下2个问题:

1.浏览器对新的HTML5HistoryAPI的支持不一;

2.不支持的浏览器我们如何解决前进/后退的问题;

对于问题1,我们采用的是hash方案,这也是很多方案采用的办法了;主要原理这里不细说了,大家可以搜索一下。

下面是我写的解决方案;大家可以参考下,欢迎互相探讨。

github地址:https://github.com/zawaliang/History

6.一些参考文档

相关推荐