Ajax保留浏览器历史的两种解决方案(Hash&Pjax)
Posted 全栈开发者中心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ajax保留浏览器历史的两种解决方案(Hash&Pjax)相关的知识,希望对你有一定的参考价值。
一、通过锚点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";
};
二、通过html5加强型的History对象实现(类Pjax)
来模拟一下github的环境,github中每个url是对应一个完整的实际页面的,所以在ajax请求页面时需要异步获取target页面中指定id容器中的内容:
比如有这样两个页面:
index.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
<title>index</title>
</head>
<body>
<script>document.write(new Date());</script>
<div id="cn">
<a href="second.html">加载前</a>
</div>
</body>
</html>
second.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
<title>second</title>
</head>
<body>
<script>document.write(new Date());</script>
<div id="cn">
<a href="index.html">加载后</a>
</div>
</body>
</html>
假如用同步的http请求打开的话完全是两个页面,两个页面加入很多地方一样的话我们完全可以用这种方法来实现ajax请求变更DOM,我在这里加了<script>document.write(new Date());</script>语句通过它的变化能得知是否取自两个http请求,局
部的ajax请求是不会改变这个时间显示的。
$(function() {
var state = {
title: "index",
url: "index.html"
};
$("#cn").click(function() {
window.history.pushState(state, "index", "second.html");
var $self = $(this);
$.ajax({
url: "second.html",
dataType: "html",
complete: function(jqXHR, status, responseText) {
responseText = jqXHR.responseText;
if (jqXHR.isResolved()) {
jqXHR.done(function(r) {
responseText = r;
});
$self.html($("<div>").append(responseText.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "")).find("#cn"));
}
}
});
document.title = "second";
return false;
});
$(window).bind('popstate', function(e) {
var st = e.state;
//$("#cn").load(st.url + " #cn");
$.ajax({
url: "index.html",
dataType: "html",
complete: function(jqXHR, status, responseText) {
responseText = jqXHR.responseText;
if (jqXHR.isResolved()) {
jqXHR.done(function(r) {
responseText = r;
});
$("#cn").html($("<div>").append(responseText.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "")).find("#cn"));
}
}
});
document.title = e.state.title;
});
});
$("#cn").html($("<div>").append(responseText.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "")).find("#cn"));
先创建一个div容器在将经过script过滤过的代码装入这个容器在通过find方法找到里面对应的选择器容器插入本身的页面中,这里可以不用html来填充,可以根据自己的项目需要用slideUp,show什么的特效进行内容显示~~
另外这里要推荐一个jQuery组件叫pjax(https://github.com/defunkt/jquery-pjax),比较牛叉的一个组件,异步的部分load进来另外一个页面对应容器中的内容,实现的机理和我上面的第二种方案一致。pushState + ajax = pjax 感觉这个应用会热起来的。
如pjax最后的一段无奈的兼容处理:
$.support.pjax = window.history && window.history.pushState
// Fall back to normalcy for older browsers.
if ( !$.support.pjax ) {
$.pjax = function( options ) {
window.location = $.isFunction(options.url) ? options.url() : options.url
}
$.fn.pjax = function() { return this }
}
via:http://leyteris.iteye.com/blog/1107597
以上是关于Ajax保留浏览器历史的两种解决方案(Hash&Pjax)的主要内容,如果未能解决你的问题,请参考以下文章