Ошибка Chrome onpopstate / pushState?
Прежде всего, я не совсем уверен, что я делаю или ожидаю, правильно. Похоже, документации об этом не так много, но то, что я прочитал, говорит о том, что это должно работать.
Я столкнулся с некоторыми проблемами при попытке использовать history.pushState, поэтому в итоге я создал демонстрационную страницу, чтобы увидеть, что происходит не так.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js" ></script>
<script>
window.onpopstate = function()
{
var d = new Date;
console.log(d.toString());
console.log(document.location.href);
};
$(document).ready(function()
{
$('#push').click(function()
{
var rand = Math.random();
history.pushState( {'number':rand} , 'Test '+rand , '/test/'+rand );
return false;
});
});
</script>
</head>
<body>
<a href="#" id="push">New state</a>
</body>
</html>
Когда я нажимаю ссылку "новое состояние", я ожидаю увидеть в консоли, что функция onpopstate была запущена, и я увижу новый URL (что-то вроде test/[number]).
Расположение в адресной строке в Chrome обновляется, но событие onpopstate никогда не запускается. Затем, когда я нажимаю кнопку "Назад" в браузере, создается впечатление, что запускаются несколько событий. Похоже, что когда бы я ни использовал кнопки навигации в браузере, каждое всплывающее событие, которое должно было произойти, происходит одновременно.
Это сложно объяснить. Вот что я ожидаю увидеть в консоли.
Загрузите страницу. Chrome запускает начальное событие popstate при загрузке страницы
popstate.html:13Sat 19 ноября 2011 16:23:48 GMT+0000 (стандартное время GMT)
popstate.html: 14http: //example.com/popstate.html
Нажмите на ссылку "новое состояние". Местоположение в адресной строке обновляется по адресу http://example.com/test/0.06458491436205804.
Сб 19 Ноя 2011 16:23:53 GMT+0000 (Стандартное время по Гринвичу)
popstate.html: 14http: //example.com/test/0.06458491436205804
Нажмите кнопку назад в браузере. URL-адрес в адресной строке возвращается к /popstate.html
popstate.html:13Sat 19 ноября 2011 16:26:27 GMT+0000 (стандартное время GMT)
popstate.html: 14http: //example.com/popstate.html
Это то, что я ожидаю. Вот что я на самом деле вижу...
Загрузить страницу
popstate.html:13Sat 19 ноября 2011 16:27:42 GMT+0000 (стандартное время GMT)
popstate.html: 14http: //example.com/popstate.html
Нажмите на ссылку нового состояния. Ничего не появляется в консоли. Адресная строка меняется на /test/0.5458911096211523
Нажмите кнопку назад в браузере. Адрес меняется обратно на /popstate.html
popstate.html:13Sat 19 ноября 2011 16:27:42 GMT+0000 (стандартное время GMT)
popstate.html: 14http: //example.com/popstate.html
popstate.html:13Sat 19 ноября 2011 16:28:57 GMT+0000 (стандартное время GMT)
popstate.html: 14http: //example.com/popstate.html
Как вы можете видеть, он повторяет исходное popstate и показывает возврат в /popstate.html, но никогда не срабатывает для заданного состояния. Если я теперь нажму вперед в браузере, я получу:
popstate.html:13Sat 19 ноября 2011 16:27:42 GMT+0000 (стандартное время GMT)
popstate.html: 14http: //example.com/popstate.html
popstate.html:13Sat 19 ноября 2011 16:28:57 GMT+0000 (стандартное время GMT)
popstate.html: 14http: //example.com/popstate.html
popstate.html:13Sat 19 ноября 2011 16:29:58 GMT+0000 (стандартное время GMT)
popstate.html: 14http: //example.com/test/0.5458911096211523
(Все они появляются снова, вот скриншот: http://img.ctrlv.in/4ec7da04e20d3.jpg)
Я не знаю, делаю ли я это неправильно, мои ожидания ошибочны, или это на самом деле ошибка?
Заранее спасибо всем, кто прочитал все это и может пролить свет на это для меня.
2 ответа
Хром console.log
не может справиться с вещами, когда вы переходите на другие страницы. Вы можете подтвердить это, потому что он регистрирует несколько вещей одновременно с другими временными метками (что невозможно). Вы бы лучше использовать $("body").append
войти сюда (или добавить к какому-либо другому элементу).
Во-вторых, когда вы выдвигаете состояние, то, очевидно, оно не появляется, поэтому popstate
Событие не вызвано. Если вы хотите, чтобы вызвать onpopstate
обработчик, когда вы выдвигаете состояние, вы также можете создать простую оболочку, например: http://jsfiddle.net/vsb23/2/.
function load(url, state) { // logging function; normally load AJAX stuff here
$("pre").append(new Date
+ "\n" + url
+ "\n" + JSON.stringify(state) // to log object as string
+ "\n\n");
}
function pushState(data, title, url) {
history.pushState(data, title, url);
load(location.href, data); // call load function when pushing as well
}
window.onpopstate = function(e) {
load(location.href, e.state);
};
$("button").click(function() {
pushState({foo: "bar"}, "test", "/test?a=b"); // sample push
});
Изменить: Это уже ошибка на трекер ошибок Chromium.
if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1 !== true) {
runpopState();
}
function runpopState() {
alert("POP STATE");
}
window.onpopstate = function () {
runpopState();
};
Пока они не исправят ошибку, такого решения будет достаточно.