修改 hash 值保持 tab、ajax 前进后退的历史记录

页面后退返回,保持原来的点击过的 tab 状态;页面后退返回,保持原来请求过的 ajax 状态。这是一个用户体验的极大提升之处嘢,产品和技术的观点竟然一致了啊!

后退保持 tab 点击过的状态

总体思路:

  1. 每点击一次导航中的任一 li ,切换对应的 tab 内容、同时把当前 tab 的索引值 index ,更新设置为当前的 hash 值;
  2. 点击跳转到其它页面再 后退 回来时,获取 url 中的 hash 值;去除 # ,即为上次离开时点击过的索引值 index;
  3. 根据该索引值 index ,自动为该索引所对应的 导航 tab li 执行一次点击,即可看到之前的 tab 状态。

直接 demo 说事直接:
html 是一个 tab 结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- tab 导航菜单 -->
<div id="cont-top">
<ul>
<li class="top-active"><a>最近购买</a></li>
<li><a>最新</a></li>
<li><a>最热</a></li>
<li><a>全部游戏</a></li>
</ul>
</div>
<!-- tab 对应导航的四个内容块 -->
<div id="cont-main">
<ul class="main-one" id="one-lately">
<li><a href="http://gjincai.github.io" class="hash-test">a链接跳走</a></li>
</ul>
<ul class="main-one" id="one-new">
<li><a href="http://gjincai.github.io" class="hash-test">a链接跳走</a></li>
</ul>
<ul class="main-one" id="one-hot">
<li><a href="http://gjincai.github.io" class="hash-test">a链接跳走</a></li>
</ul>
<ul class="main-one" id="one-all">
<li><a href="http://gjincai.github.io" class="hash-test">a链接跳走</a></li>
</ul>
</div>

jquery 设置 hash :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$(function(){
//tab 点击切换
$('#cont-top li').on('click',function(){
$(this).siblings('li').removeClass('top-active').end().addClass('top-active');
$('.main-one').css('display','none');
$('.main-one').eq($(this).index()).css('display','block');
//对应当前的 索引值index 、设置 hash值
location.hash="#"+$(this).index();
});
});
$(function(){
var nowHash=location.hash; //页面后退载入时,获取 hash
nowHash=nowHash.substr(1); //去除 hash值 中的 #,即为之前点击状态的 index索引值
$('#cont-top li').eq(nowHash).trigger('click'); //根据 index索引值 ,自动点击一次
});

ajax 保持页面的前进后退历史记录

由上面的 tab后退保持点击过的状态,可以顺势展开蔓延至 ajax的保前进后退的状态记录。

假如上面 tab 内容块 #cont-main 下的 4个 ul 是异步请求的,那么总体思路流程、与上面的保持 tab 状态相似,只是在单击导航 tab li 时增加 $.ajax({}); 然后根据 索引值index(即hash值)去再执行一次异步请求、即可保持 ajax 的前进后退状态了。

扩展:
1、后退返回、重新加载页面时,为了能自动执行获取 hash值、根据 hash值 自执行操作,上面使用的方法是、把代码放在单独的一个 $(function(){}); 中:

1
2
3
4
5
$(function(){
var nowHash=location.hash; //页面后退载入时,获取 hash
nowHash=nowHash.substr(1); //去除 hash值 中的 #,即为之前点击状态的 index索引值
$('#cont-top li').eq(nowHash).trigger('click'); //根据 index索引值 ,自动点击一次
});

2、其实,window.onhashchange 可以用来监听监听 URL 的 hash值 变化。(只是,ie7 及其以下不支持)。可以通过它来监听 hash 的变化、进而执行相应的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//判别ie && documentMode在IE8+中被支持
if(document.all && !document.documentMode){
setInterval(changeHashCallBack, 100);
alert('<IE8');
}else{
window.onhashchange = changeHashCallBack;
}
function changeHashCallBack(){
var nowHash=location.hash; //页面后退载入时,获取 hash
nowHash=nowHash.substr(1); //去除 hash值 中的 #,即为之前点击状态的 index索引值
$('#cont-top li').eq(nowHash).trigger('click'); //根据 index索引值 ,自动点击一次
});
}

HTML5 history 实现 ajax 的前进后退

html5 的 history 已经可以简单实现以上功能了!( IE(10.0+)支持,具体支持情况查看这里 Can i use) 。

HTML5 history API 有
2个方法: history.pushState()history.replaceState()
1个事件: window.onpopstate

  • history.pushState(stateObject, title, url) :新生成一条新的历史记录。
    eg:
1
2
var pageCur="data1";
history.pushState(null, "页面标题", "?page=" + pageCur);

参数1,状态对象(如:{} , null);
参数2,页面标题,目前被各浏览忽略,暂且一般设置为空(或随意);
参数3,url 地址,以当前 url 为基础,在其后添加上,eg: "?page=data1"

  • history.replaceState(stateObject, title, url) :用法基本同上;
    注意:替换当前的 url ,不会新生成 url。

  • window.onpopstate:前进、后退、history.back() 时触发(所切换的页面中的 javascript、document的全局环境需相同)。
    pushState、replaceState 的参数1、通过 state 传入:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //js
    window.addEventListener("popstate", function() {
    var currentState = history.state;
    });
    //jquery
    $(window).on("popstate", function(event) {
    // jQuery对event做了一层包装,需通过originalEvent取得原生event。
    var currentState = event.originalEvent.state,
    });