окно привязки POPSTATE - PullRequest
       2

окно привязки POPSTATE

29 голосов
/ 14 января 2011

Учитывая следующее:

$(window).bind("popstate", function() {
    alert('popstate');
});

При первой загрузке предупреждение срабатывает с FireFox и Chrome, но не с Safari. Это почему? Кто-нибудь еще видел это и знает, как лучше всего решить это?

Ответы [ 8 ]

45 голосов
/ 11 мая 2011

Смотрите код из pjax.В настоящее время pjax является довольно популярной библиотекой с открытым исходным кодом, поэтому нижеприведенная логика может быть лучшей, чтобы избежать этой проблемы.

17 голосов
/ 15 мая 2012

В webkit событие popstate запускается при загрузке страницы. Чтобы избежать этого, этот легкий обходной путь работает для меня:

Каждый раз, когда я запускаю history.push(...), я добавляю class исторически нажатой к тегу body:

history.push(...);
$("body").addClass("historypushed");

Когда я запускаю событие popstate, я проверяю этот класс:

$(window).bind('popstate', function(e) {
 if($("body").hasClass("historypushed")) { 
  /* my code */ 
 } 
});
15 голосов
/ 01 апреля 2011

Ситуация теперь обратная.Chrome исправил ошибку и теперь запускает popstate при загрузке страницы, но Firefox 4 (начиная с RC) отошел от спецификации, и теперь не запускает popstate !

ОБНОВЛЕНИЕ : спецификация HTML5 была изменена в 2011 году, так что состояние popstate не должно запускаться при загрузке страницы.И Firefox, и Chrome теперь делают то же самое, что и Firefox 4 и Chrome 34 .

3 голосов
/ 10 ноября 2012

Простой способ избежать этой проблемы - установить для первого аргумента pushState значение true, а затем проверить его на onpopstate.Похож на пример с pjax, но немного проще.Приведенный ниже пример будет запускать doSomething () для каждого события popstate, за исключением загрузки первой страницы.

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();
      }
    });
  }
}
2 голосов
/ 21 февраля 2011

В Webkit была ошибка, из-за которой неправильно реализовано событие «popstate».Прочтите этот простой пост, объясняющий проблему (классное маленькое шоу и расскажите): http://www.bcherry.net/playground/pushstate

Я бы предложил реализовать собственный трекер событий "popstate" для Safari.Примерно так:

$(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
});

Вы можете заключить этот оператор в тест браузера, чтобы проверить наличие сафари.Еще лучше посмотреть, было ли запущено «popstate» ко времени готовности DOM, а затем применить внутреннюю функцию для замены реализации.Единственное, чего вы не хотите, это запускать два события popstate (дублирование логики вашего обработчика событий, отличный способ заблокировать пользовательский интерфейс).

0 голосов
/ 20 ноября 2015

Этот ответ на похожий вопрос предлагает проверить булеву истинность event.state в обработчике popstate:

window.addEventListener('popstate', function(event) {
    if (event.state) {
        alert('!');
    }
}, false);

Вы также можете привязать свою функцию обратного вызова к событию popstate, например:

window.onpopstate = callback();

Проверьте здесь для получения дополнительной информации об этом решении

0 голосов
/ 07 мая 2015

Я конвертирую ответы @Nobu & @Tamlyn в объект, а также добавляю небольшое исправление, добавляя "window.history.state! == null".В некоторых браузерах history.state существует, но он нулевой, поэтому он не работал.

/**
 * 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!

0 голосов
/ 05 декабря 2011

Это мой обходной путь.

window.setTimeout(function() {
  window.addEventListener('popstate', function() {
    // ...
  });
}, 1000);
...