Я разрабатываю веб-страницу, где в зависимости от следующих или обратных действий я выполняю соответствующую анимацию, проблема возникает при использовании pushstate. Когда я получаю событие, как мне узнать, нажал ли пользователь кнопки истории назад или вперед с помощью Pushstate API? Или мне нужно что-то реализовать самостоятельно?
Как мне узнать, возникает ли событие popstate из действий назад или вперед с помощью pushstate HTML5?
Ответы (2)
Вы должны реализовать это самостоятельно, что довольно легко.
- При вызове
pushState
присвойте объекту данных уникальный увеличивающийся идентификатор (uid). - Когда вызывается
onpopstate
обработчик; проверьте uid состояния на постоянную переменную, содержащую uid последнего состояния. - Обновите постоянную переменную с помощью uid текущего состояния.
- Выполняйте разные действия в зависимости от того, был ли uid состояния больше или меньше uid последнего состояния.
[a, b, a]
вы получаете popstate
событие, как узнать, было ли оно назад или вперед?
- person david_adler; 28.05.2021
Этот ответ должен работать с одностраничным приложением push-state, многостраничным приложением или их комбинацией. (Исправлено, чтобы исправить ошибку History.length
, указанную в комментарии Мескалито.)
Как это работает
Мы можем легко прослушивать новые записи в стеке истории. Мы знаем, что для каждой новой записи спецификация требует, чтобы браузер:
- "Удалить все записи в истории сеансов контекста просмотра после текущей записи"
- «Добавить новую запись в конце»
Таким образом, в момент въезда:
новая позиция входа = позиция последнего показа + 1
Тогда решение:
- Пометить каждую запись истории собственной позицией в стеке
- Следите в хранилище сеансов за последней показанной позицией
- Узнайте направление движения, сравнив два
Пример кода
function reorient() // After travelling in the history stack
{
const positionLastShown = Number( // If none, then zero
sessionStorage.getItem( 'positionLastShown' ));
let position = history.state; // Absolute position in stack
if( position === null ) // Meaning a new entry on the stack
{
position = positionLastShown + 1; // Top of stack
// (1) Stamp the entry with its own position in the stack
history.replaceState( position, /*no title*/'' );
}
// (2) Keep track of the last position shown
sessionStorage.setItem( 'positionLastShown', String(position) );
// (3) Discover the direction of travel by comparing the two
const direction = Math.sign( position - positionLastShown );
console.log( 'Travel direction is ' + direction );
// One of backward (-1), reload (0) and forward (1)
}
addEventListener( 'pageshow', reorient );
addEventListener( 'popstate', reorient ); // Travel in same page
См. Также живую копию кода.
Ограничение
Это решение игнорирует записи истории внешних страниц, чуждых приложению, как если бы пользователь никогда их не посещал. Он рассчитывает направление движения только по отношению к последней показанной странице приложения, независимо от любой внешней страницы, посещенной между ними. Если вы ожидаете, что пользователь поместит сторонние записи в стек (см. Комментарий Atomosk), вам может потребоваться обходной путь.
const direction = Math.sign(history.length - (sessionStorage.getItem('stateLastShown') || 0)); sessionStorage.setItem('stateLastShown', history.length);
, поскольку вы всегда помещаете history.length
в состояние истории.
- person Atomosk; 19.03.2018
history.length
всегда будет давать одно и то же число (50 в моем случае), поэтому это решение всегда будет возвращать 0 в качестве направления, потому что все записи состояния будут иметь идентичная позиция.
- person Mesqalito; 28.01.2019
History.length
делают его ненадежным. Я изменил ответ, чтобы вместо этого использовать переменную сеанса positionLastShown
.
- person Michael Allan; 09.05.2019