Comments 38
Завидую вам с вашими заказчиками.
Мне около полугода тому назад пришлось опять IETester ставить. Некоторые заказчики такие заказчики.
Мне около полугода тому назад пришлось опять IETester ставить. Некоторые заказчики такие заказчики.
Откуда взялось
location: example.com/example.html, state: nullи куда делось
history.pushState({page: 2}, «title 2», "?page=2");?
1. после двух history.back() вы вернетесь к самому первому состоянию, когда сайт был загружен.
2. Оно было заменено состоянием ({page: 3}, «title 3», "?page=3");
2. Оно было заменено состоянием ({page: 3}, «title 3», "?page=3");
history.pushState({page: 2}, "title 2", "?page=2");
// заменить текущее состояние
history.replaceState({page: 3}, "title 3", "?page=3");
Нумерация страниц путает ужасно.
Поясните, пожалуйста, когда мы делаем back(), то переход идёт к первому запушенному состоянию?
Если так, то я всё ещё не понимаю, куда делась page 2?
И когда go(2) почему попадаем на page3?
Поясните, пожалуйста, когда мы делаем back(), то переход идёт к первому запушенному состоянию?
Если так, то я всё ещё не понимаю, куда делась page 2?
И когда go(2) почему попадаем на page3?
back() — переход к предыдущему состоянию.
изначально имеем страницу «example.com/example.html». стек состояний пуст.
изначально имеем страницу «example.com/example.html». стек состояний пуст.
history.pushState({page: 1}, "title 1", "?page=1"); // location: http://example.com/example.html?page=1, state: {"page":1}
// теперь стек сотояний [null, {page: 1}]
history.pushState({page: 2}, "title 2", "?page=2"); // location: http://example.com/example.html?page=2, state: {"page":2}
// теперь стек сотояний [null, {page: 1}, {page: 2}]
history.replaceState({page: 3}, "title 3", "?page=3"); // location: http://example.com/example.html?page=3, state: {"page":3}
// здесь мы заменили текущее состояние, а не добавили его. поэтому грубо стек состояний таков:
[null, {page: 1}, {page:3}]
// Переходим назад по истории, получаем состояние {page: 1}
history.back(); // location: http://example.com/example.html?page=1, state: {"page":1}
// Переходим назад по истории, получаем состояние null
history.back(); // location: http://example.com/example.html, state: null
// Переходим на два состояния вперед, получаем состояние {page: 3}
history.go(2); // location: http://example.com/example.html?page=3, state: {"page":3}
Я для себя давно написал маленький универсальный объект для работы с url.
Если браузер тянет History api — работаем с ним, если нет — то с hash.
Вот, может кому-то еще пригодится. Использовать просто:
Рабочий пример — просто покликайте по фильтру.
Если браузер тянет History api — работаем с ним, если нет — то с hash.
Вот, может кому-то еще пригодится. Использовать просто:
Hash.add('key1', 'var1'); // добавляем значение в url
Hash.remove('key1'); // удаляем
Hash.set({'key1':'var1'}); // заменяем все значения своим массивом
Hash.get(); // получаем данные в url массивом
Hash.clear(); // удаляем все значения в url без перезагрузки
Рабочий пример — просто покликайте по фильтру.
Странно кликаю по фильтру норм и ссылка меняется и содержимое, щелкаю назад меняется только ссылка содержимое как было так и осталось.
Есть готовые полифилы HTML5-History-API от devote, мой форк, которые делают тоже самое, но только прозрачно для пользователя. У себя в форке я ещё добавил событие pagechange которое срабатывает и на методы pushState/replaceState, и на событие popstate
Если вы пушите событие (первый параметр), то могли бы пояснить, как он может использоваться, благо работает он как положено. А вот второй параметр (title), не работает для большинства браузеров, title страницы надо вручную менять через document.title чтобы работало как положено — опять же не помешает добавить в статью.
А вот второй параметр (title), не работает для большинства браузеров, title страницы надо вручную менять через document.title чтобы работало как положено
Ну это не проблема… Исходя из примера:
// Обработчик back/forward событий
window.onpopstate = function(event) {
console.log("location: " + location.href + ", state: " + JSON.stringify(event.state));
// меняем title
document.title = event.state.title;
};
// добавить состояние истории
history.pushState({page: 1, title: "title 1"}, "", "?page=1");
history.pushState({page: 2, title: "title 2"}, "", "?page=2");
// заменить текущее состояние
history.replaceState({page: 3, title: "title 3"}, "", "?page=3");
Все верно, осталось только дописать как хранить динамический контент в event.state, чтобы не перезагружать страницу при нажатиях back и forward, потом убедить автора добавить это в статью и лично я буду абсолютно доволен :)
осталось только дописать как хранить динамический контент в event.state
Не самый лучший вариант, но тоже имеет право на жизнь :)
<html>
<head>
<title>Some Title</title>
</head>
<body>
<a href="?page=1" title="Title 1">Page 1</a>
<a href="?page=2" title="Title 2">Page 2</a>
<a href="?page=3">Page 3</a>
<script>
window.onpopstate = function (event) {
document.title = event.state.title;
};
var a = document.querySelectorAll('a');
for (var i=0; i < a.length; i++) {
a[i].onclick = function() {
var title = document.title = this.title ? this.title : this.innerHTML;
history.pushState({title: title}, "", this.href);
return false;
}
}
</script>
</body>
</html>
Вы либо меня не поняли, либо упростили пример так, что потерялась сама идея, хранить в первом параметре состояние\контент динамического блока\блоков (того что вы аяксом грузите н-р).
И к слову вместо ?page=1 и ?page=2, можно сделать красивые /page1 и /page2 (нужно будет чутка только в .htaccess подшаманить, чтоб букмарки открывались так, как ожидает пользователь), главная идея статьи избавиться от hash, так что почему не сделать симпатичный URL, вообще без параметров сходу.
Я может придираюсь через чур, но как заметили ниже, статья введение на хабре уже была, раз уж это уже вторая о том же, можно было бы довести до полезного на практике примера.
И к слову вместо ?page=1 и ?page=2, можно сделать красивые /page1 и /page2 (нужно будет чутка только в .htaccess подшаманить, чтоб букмарки открывались так, как ожидает пользователь), главная идея статьи избавиться от hash, так что почему не сделать симпатичный URL, вообще без параметров сходу.
Я может придираюсь через чур, но как заметили ниже, статья введение на хабре уже была, раз уж это уже вторая о том же, можно было бы довести до полезного на практике примера.
Вы либо меня не поняли…
И к слову вместо ?page=1 и ?page=2, можно сделать красивые /page1 и /page2Это понятно… ?page=1 и ?page=2 взяты из примера самой статьи
нужно будет чутка только в .htaccess подшаманить, чтоб букмарки открывались так, как ожидает пользовательПишу на python/django по-этому ничего шаманить не надо
Я может придираюсь через чур, но как заметили ниже, статья введение на хабре уже была, раз уж это уже вторая о том же, можно было бы довести до полезного на практике примера.с этим я согласен… но акцент был на поддержку браузеров (то бишь даже ie поддерживает)
А вот второй параметр (title), не работает для большинства браузеров, title страницы надо вручную менять через document.title чтобы работало как положено
Если внимательно прочесть спецификацию, второй параметр никак не относиться к title страницы. И говорить о том что он не работает, не совсем правильно.
Суть данного параметра в том, что многие привыкли читать название параметра как title и воспринимать его как title-страницы (грубо сопоставлять с document.title), что является ошибочным. Этот параметр не имеет ничего общего с document.title. Он нужен для того что бы менять имя страницы в истории. Для примера это имя вы можете увидеть при продолжительном нажатии на кнопки back/forward, то есть попробуйте нажать левой клавишей мыши на одну из этих стрелок с небольшой задержкой, откроется список, вот в нем и будут отображаться те самые имена что были занесены во второй параметр.
Для примера это имя вы можете увидеть при продолжительном нажатии на кнопки back/forward, то есть попробуйте нажать левой клавишей мыши на одну из этих стрелок с небольшой задержкой, откроется список, вот в нем и будут отображаться те самые имена что были занесены во второй параметр.
Параметр title никак к этому не относится!
В историю вписывается то что в:
<title>Some Title</title>
или в случае с javascript'ом:
document.title = "Some Title";
вы так утверждаете лишь потому что браузеры в реальности пишут туда заголовок из document.title, хотя в реальности так работать не должно (то есть должно но не в случае с pushState/replaceState). Хотя например Opera 12 (если моя память не изменяет) пишет то что попадает вторым параметром в pushState/replaceState, то есть поступает правильно в отличии от других браузеров.
попробуйте открыть в Опере 12 консоль и вбить:
После проделайте то о чем я писал в посте ранее
попробуйте открыть в Опере 12 консоль и вбить:
history.pushState(null, 'Новый заголовок');
history.pushState(null, 'Новый заголовок 2', '/urlurl');
После проделайте то о чем я писал в посте ранее
Стоит отметить что
А так для старых браузеров я просто перегружал страницу через
onpopstate
в хроме может вызывается при подписываниии (может тк если обернуть в setTimeout
, то результат может быть не предсказуем).А так для старых браузеров я просто перегружал страницу через
window.location = '/url'
и имел отличную возможность использовать hash
для всякого рода сообщений и выделений внутри страницы.В статьи не озвучено:
* полифилы: HTML5-History-API от devote, мой форк (используется у нас в компании)
* подводные камни при использовании History-API:
В своём форке я исправляю все эти проблемы.
В общем, использование History-API это не панацея и нужно было ещё допиливать API браузера для реального использования в крупном проекте.
* полифилы: HTML5-History-API от devote, мой форк (используется у нас в компании)
* подводные камни при использовании History-API:
- разное срабатывание onpopstate при первой загрузке страницы в Webkit/Blink и FF/Opera
- забагованые location.[pathname/href] в старых Chrome/Safari (в том числе на старых Android/iPhone) и Opera 12-: эти браузеры разэкранируют спец символы, при получении значений этих свойств, в отличии от последних версий браузеров
- Баги Opera 12- с релативными ссылками при использовании History-API: после второго применения History-API node.href указывает на урл, сформированный из предыдущего установленного через History-API значения и относительной ссылки самого элемента a
- Баг в последнем Webkit/Blink с History-API + Fullscreen API: Chromium/Safari выходят из полноэкранного режима (активированного через Fullscreen API) при использовании History-API
В своём форке я исправляю все эти проблемы.
В общем, использование History-API это не панацея и нужно было ещё допиливать API браузера для реального использования в крупном проекте.
5. Забыл добавить, что в общем-то, использование History-API не такое удобное как хотелось бы. Т.к. при использовании методов pushState/replaceState не происходит никакого события, то остальная часть приложения ничего не знает о том, что урл сменился. Поэтому в своём форке я добавил событие
диспатчится оно на window. Срабатывает и на методы pushState/replaceState и на событие popstate
pagechange = {
newUrl: string
, oldUrl: string
, popstate: boolean
}
диспатчится оно на window. Срабатывает и на методы pushState/replaceState и на событие popstate
Вот только с popstate у Chrome до сих пор проблемы. Приходится изобретать разнообразные велосипеды, чтобы оно работало как следует.
Проблем хватает у многих браузерах, пока еще ни один браузер идеально не поддерживает History-API поэтому приходиться прикручивать костыли для тех или иных случаев. В моей реализации библиотеки, о которой упомянул termi я стараюсь избавиться от подобных багов и стабилизировать работу API для всех браузеров одинаково.
У каждой технологии — свои предназначения, и если на сайтах используется ajax + поддержка IE9+ only, то в данном случае статья верная, но если разрабатывается приложение, ну, допустим под VK, под FB, под мэил.ру или одноклассники уж на худой конец, то тут Вы ошибаетесь просто катастрофически, просто потому, что History API просто не работает в айфреймах, и не важно какой браузер.
Никто и не говорит о приложениях под соцсети, поэтому фраза «тут Вы ошибаетесь» не думаю что уместна. Там свои причуды которые нужно выносить в отдельную статью и обсуждения.
Один я не понимаю зачем History API использовать в фреймах?
Sign up to leave a comment.
Прекратите использовать location.hash, да здравствует HTML5 History API!