LINUX.ORG.RU

Аналог beforeunload для History API

 ,


0

1

JS позволяет потребовать у юзера подтверждение при закрытии страницы. Например, если на веб-странице содержится какой-нибудь редактор или важная форма и разработчик хочет напомнить юзеру сохранить несохранённое перед выходом. Для этого есть специальное событие beforeunload, в котором можно установить returnValue = true, если мы знаем, что не все данные сохранены.

Однако, beforeunload не работает при навигации с использованием History API. Это не беда для навигации с помощью pushState/replaceState, потому что мы сами вызываем эти функции и можем спросить подтверждение и в случае отказа просто не вызывать эти функции.

Но есть ещё событие popstate, которое происходит при нажатии кнопок Вперёд и Назад в браузере. И вот когда оно пришло, кажется, уже слишком поздно - preventDefault у него не работает, элемент истории в любом случае удаляется, так что подтверждающий диалог показывать нет смысла (мы не можем отменить навигацию).

Есть ли возможность реализовать аналог beforeunload для этой ситуации? Спросить у юзера подтверждение навигации с возможностью отмены, потому что у него есть несохранённые данные.

★★★★★

Нашёл решение: Navigation API.

Что-то вроде:

window.navigation.addEventListener("navigate", evt => {
    if (evt.userInitiated) {
        // Опционально: если не хотим ловить программную
        // навигацию через History API.
        return;
    }
    if (evt.cancelable) {
        if (hasUnsavedChanges()) {
            if (!confirm(
                "Are you sure that you want to leave current page? " +
                "You might lose unsaved data."
            )) {
                evt.preventDefault();
                return;
            }
        }
    } else {
        // Скорее всего сможем поймать через "beforeunload"
    }
    if (evt.canIntercept) {
        // Можно также использовать evt.intercept() вместо того,
        // чтобы самому обрабатывать клики по ссылкам и события
        // "popstate", чтобы загружать и рендерить контент
        // без перезагрузки целой страницы.
        // Пример: https://developer.mozilla.org/en-US/docs/Web/API/NavigateEvent/intercept#examples
    }
});

window.addEventListener("beforeunload", evt => {
    if (hasUnsavedChanges()) {
        evt.returnValue = true;
    }
});

На текущий момент поддерживается в Chromium-based браузерах (Google Chrome, Opera, Edge и т. п.) и не поддерживается в Firefox и Safari. В них судя по всему сейчас обрататывать переходы по истории нельзя, только закрытие страницы совсем, ну и клики по ссылкам (спрашивать прежде чем делать pushState, если есть несохранённые данные).

KivApple ★★★★★
() автор топика
Последнее исправление: KivApple (всего исправлений: 1)

Я не до конца понял, но ты же в любом случае всё сам обрабатываешь. Ну удалился элемент истории, а ты его заново вставь, сделав переход туда где ты был. АПИ же вроде есть.

vbr ★★★★
()