次の場合:
$(window).bind("popstate", function() {
alert('popstate');
});
最初の読み込み時に、FireFoxとChrome=でアラートが発生しますが、Safariでは発生しません。なぜですか?これを他の誰かが見て、これを解決する最善の方法を知っていますか?
状況は逆転した。 Chromeはバグを修正し、ページのロード時にpopstateを起動しますが、Firefox 4(RC以降)は仕様から逸脱し、- popstateを起動しません !
[〜#〜] update [〜#〜]:HTML5仕様は2011年に変更され、ページのロード時にpopstateが呼び出されないようになりました。 FirefoxとChromeはFirefox 4と Chrome 34 のように正しく動作するようになりました。
Pjaxのコードを参照してください。現在、pjaxはかなり人気のあるオープンソースライブラリです。そのため、この問題を回避するには、以下のロジックが最適です。
var popped = ('state' in window.history), initialURL = location.href
$(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
...
https://github.com/defunkt/jquery-pjax/blob/master/jquery.pjax.js
Webkitでは、ページの読み込み時にpopstateイベントが発生します。これを回避するために、この簡単な回避策は私にとってはうまくいきます:
history.Push(...)
を呼び出すたびに、class
-タグにbody
historypushedを追加します。
history.Push(...);
$("body").addClass("historypushed");
Popstateイベントをトリガーするときに、このクラスを確認します。
$(window).bind('popstate', function(e) {
if($("body").hasClass("historypushed")) {
/* my code */
}
});
この問題を回避する簡単な方法は、pushStateの最初の引数をtrueに設定してから、onpopstateをチェックすることです。 pjaxの例に似ていますが、もう少し簡単です。以下の例では、最初のページのロードを除くすべてのpopstateイベントに対してdoSomething()を実行します。
function setupPopState() {
if (history.popState) {
# immediately replace state to ensure popstate works for inital page
history.replaceState(true, null, window.location.pathname);
$(window).bind('popstate', function(event) {
if (event.originalEvent.state) {
doSomething();
}
});
}
}
Webkitには、「popstate」イベントを誤って実装するバグがありました。問題を説明するこの簡単な投稿をチェックしてください(クールな小さなショーと教え): http://www.bcherry.net/playground/pushstate
私の提案は、Safariに独自の「popstate」イベントトラッカーを実装することです。このようなもの:
$(window).load(function(){
function fire_popstate(){
$(this).trigger("popstate"); // fire it when the page first loads
}
var lasthash = window.location.hash;
setInterval(function(){
var currenthash = window.location.hash;
if(lasthash != currenthash){
fire_popstate();
}
}, 500);//check every half second if the url has changed
});
そのステートメントをブラウザのテストにラップして、サファリをチェックすることができます。 DOMの準備ができるまでに「popstate」が起動されているかどうかを確認し、内部関数を適用して実装を置き換えます。発生させたくないのは、2つのpopstateイベントを発生させることです(UIをロックするための優れた方法である、イベントハンドラーロジックの複製)。
これが私の回避策です。
window.setTimeout(function() {
window.addEventListener('popstate', function() {
// ...
});
}, 1000);
同様の質問に対するこの回答は、popstate
イベントハンドラーでevent.state
の真偽をチェックすることを提案しています:
window.addEventListener('popstate', function(event) {
if (event.state) {
alert('!');
}
}, false);
次のように、コールバック関数をpopstate
イベントに関連付けることもできます。
window.onpopstate = callback();
その解決策の詳細については、ここを確認してください
@Nobuと@Tamlynの回答をオブジェクトに変換し、「window.history.state!== null」を追加することで、少し修正を加えます。一部のブラウザでは、history.stateが存在しますが、nullであるため、機能していませんでした。
/**
* The HTML5 spec was changed in 2011 to state popstate should not
* fired on page load. Chrome(34) & Firefox(4) has fixed the bug but
* some browsers (e.g. Safari 5.1.7) are still fire the popstate on
* the page load. This object created from the Pjax Library to handle
* this issue.
*/
var popstatePageloadFix = {
popped : ('state' in window.history && window.history.state !== null),
initialUrl : location.href,
initialPop : false,
init : function() {
this.initialPop = !this.popped && location.href == this.initialUrl;
this.popped = true;
return this.initialPop;
}
};
$(window).on("popstate", function (event) {
// Ignore initial popstate that some browsers fire on page load
if ( popstatePageloadFix.init() ) return;
...
});
ありがとう@Nobu!ありがとう@Tamlyn!