我正在尝试使用ajax加载内容的HTML5历史API .
我有一堆通过相关链接连接的测试页面 . 我有这个JS,它处理这些链接的点击 . 当单击链接时,处理程序获取其href属性并将其传递给ajaxLoadPage(),该页面将所请求页面中的内容加载到当前页面的内容区域中 . (我的PHP页面设置为在正常请求时返回完整的HTML页面,但只有一大块内容,如果?fragment = true附加到请求的URL . )
然后我的click处理程序调用history.pushState()以在地址栏中显示URL并将其添加到浏览器历史记录中 .
$(document).ready(function(){
var content = $('#content');
var ajaxLoadPage = function (url) {
console.log('Loading ' + url + ' fragment');
content.load(url + '?fragment=true');
}
// Handle click event of all links with href not starting with http, https or #
$('a').not('[href^=http], [href^=https], [href^=#]').on('click', function(e){
e.preventDefault();
var href = $(this).attr('href');
ajaxLoadPage(href);
history.pushState({page:href}, null, href);
});
// This mostly works - only problem is when popstate happens and state is null
// e.g. when we try to go back to the initial page we loaded normally
$(window).bind('popstate', function(event){
console.log('Popstate');
var state = event.originalEvent.state;
console.log(state);
if (state !== null) {
if (state.page !== undefined) {
ajaxLoadPage(state.page);
}
}
});
});
使用pushState向历史记录添加URL时,还需要为popstate事件包含一个事件处理程序,以处理后退或前进按钮上的点击 . (如果你不这样做,点击后面会显示你在地址栏中推送到历史记录的URL,但页面没有更新 . )所以我的popstate处理程序抓取保存在我创建的每个条目的state属性中的URL,并将其传递给ajaxLoadPage以加载适当的内容 .
这适用于我的点击处理程序添加到历史记录的页面 . 但是当我“正常”请求浏览器时,浏览器添加到历史记录的页面会发生什么?假设我正常登陆我的第一页,然后通过点击进行ajax加载浏览我的网站 - 如果我然后尝试将历史记录返回到第一页,则最后一次单击显示第一页的URL,但不是不要在浏览器中加载页面 . 这是为什么?
我可以看到这与最后一个popstate事件的state属性有关 . 对于该事件,state属性为null,因为它只是由pushState()或replaceState()添加到历史记录中的条目,可以为其赋值 . 但我第一次加载页面是一个“正常”的请求 - 为什么浏览器不会退回并正常加载初始URL?
6 回答
这是一个较旧的问题,但使用本机javascript解决此问题的答案要简单得多 .
对于初始状态,您不应该使用
history.pushState
而是使用history.replaceState
.两种方法的所有参数都相同,唯一的区别是
pushState
创建了一条新的历史记录,因此是您的问题的根源 .replaceState
仅替换该历史记录的状态,并将按预期运行,即返回初始起始页 .我遇到了与原始问题相同的问题 . 这条线
应改为
这足以捕捉最初的流行音乐 . 然后您不需要将原始页面添加到
pushState
. 即删除以下内容:最终代码基于AJAX选项卡(并使用Mootools):
我仍然认为浏览器很乐意退回到正常请求创建的条目 . 也许当您使用pushState插入其他条目时,历史记录将以正常方式停止运行 . 但我发现了一种让我的代码更好的方法 . 您不能始终依赖包含要返回的URL的state属性 . 但是,回溯历史会改变地址栏中的URL,正如您所期望的那样,因此基于window.location加载内容可能更可靠 . 在这之后great example我改变了我的popstate处理程序,因此它根据地址栏中的URL加载内容,而不是在state属性中查找URL .
您需要注意的一件事是,当您最初点击某个页面时,某些浏览器(如Chrome)会触发一个popstate事件 . 当发生这种情况时,你会不必要地进行内容 . 所以我从优秀的pjax添加了一些代码来忽略那个初始的pop .
您可以对此JS进行的一项改进只是在浏览器支持历史记录API时附加click事件处理程序 .
我实际上发现自己今天有类似的需求,并发现你提供的代码非常有用 . 我遇到了你所遇到的同样问题,我相信你所缺少的就是将你的索引文件或主页推送到历史记录中,就像你所有后续页面一样 .
这是我为解决这个问题所做的一个例子(不确定它是否是正确答案,但它很简单且有效!):
希望这可以帮助!
我意识到这是一个老问题,但在尝试轻松管理状态时像这样,采取以下方法可能更好:
这样,您可以在添加到历史记录时在状态对象上指定可选的回调函数,然后在触发
popstate
时,将使用状态对象作为参数调用此函数 .您可以轻松扩展它以满足您的需求 .
And Finally 说:
我找到了一个奇怪的浏览器行为的解释here . 解释是
我测试了这个 - 它有效 .
这意味着无需基于window.location加载您的内容 .
我希望我不要误导 .