聊聊HTML5的histroy相关API
平时没有注意到的浏览器URL细节
Ajax技术能够大大提升网站的用户体验,我们的平台中也包括了诸多Ajax请求。这次遇到的需求场景是:当用户点击一个Tab标签,发送一次Ajax请求,服务器端给出响应后,浏览器的URL并不会对应地做出改变。而用户恰恰希望能够获取到最新的URL,这样就可以把这个URL发送给别人,别人点击该URL后进入平台看到对应的界面。
类似的体验你一定在Github上遇到过:当我们在Github上浏览一个项目下的文件时,一层层文件夹点击进去,虽然发送的都是Ajax请求,但是如果细心观察一下,浏览器的URL也是在相应改变的。

history.pushState方法
要实现这个效果,其实只需要在你的javascript click事件代码中添加一句话就可以了:
history.pushState(null, "", this.href);
我们来看看文档上是怎么描述这个方法的作用的吧:
这将让浏览器的地址栏显示href,但不会加载href页面也不会检查href是否存在。
pushState方法接收三个参数:
-
第一个参数叫状态对象(state object),任何可序列化的对象都可以,最大640K。当popstate事件被触发时,事件对象的state属性包含历史记录条目的状态对象的拷贝。
-
第二个参数当前会被浏览器忽略,所以可以暂时不去关心它。
-
第三个参数就是对应的URL,既可以是绝对路径,也可以是相对路径,但必须与当前URL同源,否则将抛出异常。
popstate事件
到目前为止,我们已经解决了发送Ajax请求URL也会相应改变的问题。我们再试试点击浏览器的回退按钮,页面并没有正常地回退,对吧?
看看我们刚才提到的popstate事件,到它发挥作用的时候啦:
$(window).bind("popstate", function () {
// 需要注意的是,getScript发送的是AJAX请求
$.getScript(location.href);
});
每当激活的histroy entry发生变化时,都会触发popstate事件。当我们点击后退按钮的时候,浏览器的URL其实已经改变了,只是页面没有变化,于是我们只要执行getScript方法,并且把当前浏览器的URL传递给它就好啦。
添加完上述代码后再试试,是不是能够正常后退了呢。
余下的工作
如果你和我一样使用Rails作为Web开发框架,那么你现在会发现还需要处理额外的工作:即在controller层相应的action中添加对HTML请求的处理。
当我们通过Ajax请求进入的新页面后,按F5刷新,请求的将是更新后的URL,这时发送的就不再是Ajax请求,而是一个正常的HTML请求,在controller层找不到对应的请求处理方式的话,将会报错。
