如何控制浏览器的历史记录

1349次阅读  |  发布于5年以前

上次一位网友在我blog留言问到如何修正Ajax后退失效,这是在开发Ajax应用时很常见的需求。这篇文章就简单的介绍一下怎么解决这个问题。

首先我们要清楚后退按钮会失效的原因:使用Ajax时,页面通过XMLHttpRequest来更新内容,并没有Redirect,所以浏览器不会出现前进后退。这也 是Ajax刚出来时遭到很多人批判的一个原因,其中细节可以参考这两篇文章《Ajax: 99% Bad》、《AJAX的七宗罪》。这个问题其实跟Ajax无关,不过 Ajax的出现使得一个页面实现无刷新更新更容易,这个时候人们开始意识到,一个页面发生巨大改变而不能后退是一件很痛苦的事情。

要解决这个问题,就要控制浏览器的history,在页面发生改变时往浏览器历史里插入一条记录。但是出于安全的目的,JS是不能直接操作history的。我们必须 采用其他方法:IE中,在页面中插入一个隐藏的iframe,通过改变iframe的location或者DOM,都可以在主窗口的history中产生新记录,详细 研究可以参考这篇文章;在其他浏览器(Firefox、Opera、Safari)中没有这么复杂,只需改变url就可以产生一条新的history记录,当然url 不能乱改,要不页面就跳转走了,通常我们改变的是location.hash,也就是url"#"以后的部分。下面是具体实现:

首先在页面中放一个隐藏的iframe:


<style type="text/css" title="default" media="screen">

    #history_iframe{position:absolute;top:0; left:0;width:1px; height:1px;visibility:hidden}
    </style>
    <iframe id="history_iframe" src="blank.html"></iframe>

blank.html的内容也很简单,放了一个div来存当前的hash:


<html>

      <head><title>hack iframe</title></head>
      <body><div id="state"></div></body>
    </html>

对不同浏览器采用不同方法控制history:


var isIE =
typeof(window.opera)!="object"&&window.navigator.userAgent.indexOf("MSIE")>0;

    var $ = function(s){return document.getElementById(s)};
    function update_status(str){
      if(isIE){
        try{
          var doc = $("history_iframe").contentWindow.document;
          doc.open();
          doc.write('<html><body><div id="state">'+str+'</div></body></html>');
          doc.close();
        }catch(e){}
      }
      location.hash = str;
    };

可以测试一下了:


<button onclick="update_status('test1')" >test1</button>

    <button onclick="update_status('test2')" >test2</button>
    <button onclick="update_status('test3')" >test3</button>

上面就是控制浏览器history的基本原理,通过点击三个按钮,会往浏览器写入三条历史记录,这样尽管页面依旧没有刷新,但是浏览器的前进后退却能开始工作了。剩下 的工作很简单:利用一个定时器不停的检测状态是否发生变化(IE检测iframe里state的innerText;其他浏览器检测location.hash),然 后在检测到状态改变时调用相应的方法还原页面内容。限于篇幅,这一部分代码就不贴出来了。完整的实例在这里。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8