日期:2014-05-16  浏览次数:20640 次

Ajax保留浏览器历史的两种解决方案(Hash&Pjax)

总是在github down点东西,github整个界面做的不错,体验也很好~对于其中的源代码滑动的特效最为喜欢了~刚开始以为这个只是普通的ajax请求效果,但是发现这个特效能够导致浏览器地址栏跟随变化,并且再点击前进后退按钮后又可以将代码滑回滑出~~于是乎就来研究下吧~

一、通过锚点Hash实现:

在这方面其实国内很早就有做了,比如淘宝画报,通过的是在地址栏后面加#锚点实现的,浏览器是可以识别锚点为单位的历史记录的。但不是说页面本身有这个锚点,锚点的Hash只是起到一个引导浏览器将这次的记录推入历史记录栈顶的作用。

来做一个小小的demo:

    <style type="text/css">
        #tab1_header,#tab2_header{
            cursor:pointer;
            border:1px solid;
            width:50px;
        }
        #tab1,#tab2{
            width:90%;
            height:200px;
            border:1px solid;
        }
    </style>
    <div id="tab_header">
    	<span id="tab1_header">Tab1</span>
    	<span id="tab2_header">Tab2</span>
    </div>
    <div id="tab1">1</div>
    <div id="tab2">2</div>

?一个很简单的Tab切换如果一般情况下就直接:

?

$("#tab1_header").click(function() {
            $("#tab2").hide();
            $("#tab1").show();
});
$("#tab2_header").click(function() {
            $("#tab1").hide();
            $("#tab2").show();
});

但假如点击到tab2时想通过后退按钮退到tab1时就不行了,假如刷新的话浏览器的行为完全不是出于用户的想法,这样的话,我们可以加入#锚点来模拟新页面,为什么要说模拟呢,假如直接通过js改变window.location浏览器会重新加载页面,但加#就不会重新加载并且能保存在历史中。JS通过window.location.hash来控制URL后面的锚点#。

我们把代码改为这样:

$(function(){
			showTab();
			$(window).bind('hashchange', function(e){
				showTab();
			});
			$("#tab1_header").click(showTab1);
			$("#tab2_header").click(showTab2);
		});

        function showTab() {
            if (window.location.hash == "#tab2"){
				showTab2();
			} else {
				showTab1();
			}
        }
        function showTab1() {
            $("#tab2").hide();
            $("#tab1").show();
            window.location.hash = "#tab1";
        };
        function showTab2() {
            $("#tab1").hide();
            $("#tab2").show();
            window.location.hash = "#tab2";
        };

? 加上window.location.hash = "#tab1"这一段代码就行了,在点击tab后,地址栏后面就会加上#tab1,点击tab2后就会改成#tab2,当浏览器检测到url变化时就会触发hashchange这一事件,就是用户在点击后退时能够得到的事件就能够通过window.location.hash进行判断并进行ajax操作了,但是haschange这个事件并不是每个浏览器都有的,只有现代高级浏

览器才有,所以在低级的浏览器中需要用轮询来检测URL是否在变化,这个这里就不具体说了。


二、通过HTML5加强型的History对象实现(类Pjax)