spl*_*ter 94 html5 google-chrome javascript-events browser-history
我正在为我的网络应用程序使用History API,但有一个问题.我执行Ajax调用以更新页面上的一些结果并使用history.pushState()来更新浏览器的位置栏而不重新加载页面.然后,当然,我使用window.popstate来恢复单击后退按钮时的先前状态.
问题是众所周知的 - Chrome和Firefox以不同的方式对待popstate事件.虽然Firefox没有在第一次加载时启动它,但Chrome确实如此.我想拥有Firefox风格并且不会在加载时触发事件,因为它只是在加载时使用完全相同的结果更新结果.除了使用History.js之外是否有解决方法?我不想使用它的原因是 - 它本身需要太多的JS库,因为我需要在已经有太多JS的CMS中实现它,我想最小化JS我放入它.
所以,想知道是否有办法让Chrome不加载'popstate'加载,或者有人试图使用History.js,因为所有库一起混合成一个文件.
Pav*_*sch 49
在版本19的Google Chrome中,@ spliter的解决方案停止了工作.正如@johnnymire指出的那样,Chrome 19中的history.state存在,但它是null.
我的解决方法是将window.history.state!== null添加到检查window.history中是否存在状态:
var popped = ('state' in window.history && window.history.state !== null), initialURL = location.href;
Run Code Online (Sandbox Code Playgroud)
我在所有主流浏览器和Chrome版本19和18中进行了测试.它看起来很有效.
Tor*_*ben 30
如果您不想对添加到onpopstate的每个处理程序采取特殊措施,我的解决方案可能对您有意义.此解决方案的一大优点还在于,可以在页面加载完成之前处理onpopstate事件.
只需在添加任何onpopstate处理程序之前运行此代码,一切都应该按预期工作(也就像在Mozilla ^^中).
(function() {
// There's nothing to do for older browsers ;)
if (!window.addEventListener)
return;
var blockPopstateEvent = document.readyState!="complete";
window.addEventListener("load", function() {
// The timeout ensures that popstate-events will be unblocked right
// after the load event occured, but not in the same event-loop cycle.
setTimeout(function(){ blockPopstateEvent = false; }, 0);
}, false);
window.addEventListener("popstate", function(evt) {
if (blockPopstateEvent && document.readyState=="complete") {
evt.preventDefault();
evt.stopImmediatePropagation();
}
}, false);
})();
Run Code Online (Sandbox Code Playgroud)
这个怎么运作:
Chrome,Safari和可能的其他webkit浏览器在加载文档时触发onpopstate事件.这不是预期的,因此我们阻止popstate事件,直到文档加载后的第一个事件循环cicle.这是通过preventDefault和stopImmediatePropagation调用完成的(与stopPropagation不同,stopImmediatePropagation会立即停止所有事件处理程序调用).
但是,由于当Chrome错误地触发时,文档的readyState已经"完成",我们允许opopstate事件,在文档加载完成之前已经触发,以允许在加载文档之前进行onpopstate调用.
更新2014-04-23:修复了在加载页面后执行脚本时阻止popstate事件的错误.
小智 28
仅使用setTimeout不是正确的解决方案,因为您不知道要加载内容需要多长时间,因此可能会在超时后发出popstate事件.
这是我的解决方案:https: //gist.github.com/3551566
/*
* Necessary hack because WebKit fires a popstate event on document load
* https://code.google.com/p/chromium/issues/detail?id=63040
* https://bugs.webkit.org/process_bug.cgi
*/
window.addEventListener('load', function() {
setTimeout(function() {
window.addEventListener('popstate', function() {
...
});
}, 0);
});
Run Code Online (Sandbox Code Playgroud)
spl*_*ter 25
该解决方案已在jquery.pjax.js第195-225行中找到:
// Used to detect initial (useless) popstate.
// If history.state exists, assume browser isn't going to fire initial popstate.
var popped = ('state' in window.history), initialURL = location.href
// popstate handler takes care of the back and forward buttons
//
// You probably shouldn't use pjax on pages with other pushState
// stuff yet.
$(window).bind('popstate', function(event){
// Ignore inital popstate that some browsers fire on page load
var initialPop = !popped && location.href == initialURL
popped = true
if ( initialPop ) return
var state = event.state
if ( state && state.pjax ) {
var container = state.pjax
if ( $(container+'').length )
$.pjax({
url: state.url || location.href,
fragment: state.fragment,
container: container,
push: false,
timeout: state.timeout
})
else
window.location = location.href
}
})
Run Code Online (Sandbox Code Playgroud)
Tom*_*zie 14
比重新实现pjax更直接的解决方案是在pushState上设置变量,并在popState上检查变量,因此初始popState不会在加载时不一致地触发(不是jquery特定的解决方案,只是将它用于事件):
$(window).bind('popstate', function (ev){
if (!window.history.ready && !ev.originalEvent.state)
return; // workaround for popstate on load
});
// ... later ...
function doNavigation(nextPageId) {
window.history.ready = true;
history.pushState(state, null, 'content.php?id='+ nextPageId);
// ajax in content instead of loading server-side
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
50450 次 |
| 最近记录: |