现在有越来越多的需求,需要在一个复杂页面(有很多ajax异步操作,使用 js 来控制页面的展示)实现导航,书签之类的功能,同时支持浏览器向前向后浏览。由于兼容性问题,目前有三种实现的方案。这里作一下简要记录:
1. pushState
html5 提供了新的 history api,可以让开发者动态修改浏览器的url,而不会引起整个页面的重绘,给用户带来更好的体验,api 定义如下:
window.history.pushState( data, title [, url ] )Pushes the given data onto the session history, with the given title, and, if provided and not null, the given URL.
一个简单的监听方法如下所示:
window.addEventListener("popstate", function(e) {
// 执行恢复工作
// history.state 即为之前设置的 data 数据
});
可以参考一些更详细的说明:
2. hashchange 事件
当浏览器不支持pushState特性的时候,可以使用 hashchange事件(IE67得使用第三种方式),即当hash改变的时候,浏览器会自行回调,跟pushState其实原理比较像,
一个简单的编写模式如下:
window.onhashchange = hashChanged;
或者是:
window.addEventListener("hashchange", hashChanged, false);
或者是:
<body οnhashchange="hashChanged();">
在事件回调中可以根据 location.hash 拿到最新的hash值,从而执行页面的局部刷新。
在前面,我们使用 pushState来修改当前页面url,而使用 hashchange事件的时候,
可以直接修改 location.hash 来达到触发 hashchange事件。
另外,当首次进入页面的时候,这时候,不管链接有没有hash,都不会触发 hashchange事件,
所以页面要实现初始化操作,根据初始hash值作相应的初始化。
可以参考一些更详细的说明:
3. polling(轮循) ie6 和 ie7不支持 hashchange事件,通常采用的办法是使用一个隐藏的 iframe,然后通过一个定时器不断去检测iframe的hash是否跟浏览器的一致,如果不一致,则执行回调来实现。当想要修改hash的时候,可以直接修改 location.hash,因为定时器会自行去比较,然后刷新 iframe的hash.
至于为什么要使用 iframe,那是因为直接修改location的hash值之后,ie不会新增history记录,也就不支持后退操作,而刷新iframe可以增加history记录。针对ie这种顽固的浏览器,总是让人伤神。
4. 后话
可以参考 backbone.js 中 Router和History的实现,已经兼容了这三种情况,细节比较多,有兴趣的朋友可以看看。