Как * динамически * добавить / удалить перед загрузкой прослушиватель (чтобы предупредить о несохраненных изменениях) - PullRequest
0 голосов
/ 28 марта 2020

Согласно Google Page Life API API , существует два шаблона для предупреждения пользователей о несохраненных изменениях.

  1. Не рекомендуется на странице API жизненного цикла (безоговорочно добавить beforeunload слушатель):
addEventListener('beforeunload', (event) => {
  // A function that returns `true` if the page has unsaved changes.
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
}, {capture: true});
Рекомендуется API * жизненного цикла страницы (динамически добавлять / удалять прослушиватель beforeunload):
const beforeUnloadListener = (event) => {
  event.preventDefault();
  return event.returnValue = 'Are you sure you want to exit?';
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  addEventListener('beforeunload', beforeUnloadListener, {capture: true});
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  removeEventListener('beforeunload', beforeUnloadListener, {capture: true});
});

Но как действительно ли мы конвертируем метод № 1 в рекомендованный метод № 2?


Работа MWE для метода # 1 , где pageHasUnsavedChanges() реализуется с использованием jQuery serialize() и слушатель beforeunload является прямой копией вставки метода # 1:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
  </head>

  <body>
    <form>
      <input name="input">
      <button type="submit">Submit</button>
    </form>

    <script>
      // set initial state
      const getState = () => $('form').serialize();
      const state = getState();

      // add unconditional listener
      addEventListener('beforeunload', (event) => {
        if(state != getState()) {
          event.preventDefault();
          return event.returnValue = 'Are you sure you want to exit?';
        }
      }, {capture: true});
    </script>
  </body>
</html>

Если я заменю блок addEventListener рекомендованным beforeUnloadListener / onPageHasUnsavedChanges / onAllChangesSaved код, он просто говорит мне, что on* ссылки не определены.

  • Откуда * onPageHasUnsavedChanges и onAllChangesSaved откуда?
  • Или если мы должны чтобы написать их самим, каков подход для преобразования этого MWE в рекомендованный метод # 2?

Сломанный MWE для метода # 2: https://tdy.github.io/beforeunload/

При изменении формы я добавляю / удаляю beforeUnloadListener в зависимости от того, соответствует ли state getState():

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js">/script>
  </head>

  <body>
    <form>
      <input name="input">
      <button type="submit">Submit</button>
    </form>

    <script>
      // set initial state
      const getState = () => $('form').serialize();
      const state = getState();

      // save listener
      const beforeUnloadListener = (event) => {
        event.preventDefault();
        return event.returnValue = 'Are you sure you want to exit?';
      };

      // add/remove saved listener on form change
      $('form').change(() => {
        if(state != getState()) {
          addEventListener('beforeunload', beforeUnloadListener, {capture: true});
        } else {
          removeEventListener('beforeunload', beforeUnloadListener, {capture: true});
        }
      });
    </script>
  </body>
</html>

1 Ответ

0 голосов
/ 28 марта 2020

Примечание. Библиотека PageLifecycle. js предоставляет удобные методы addUnsavedChanges() и removeUnsavedChanges(), которые следуют всем рекомендациям, изложенным выше. Они основаны на черновом предложении об официальной замене события beforeunload декларативным API-интерфейсом, который на мобильных платформах использовать не так легко и надежно.

Если вы хотите правильно использовать событие beforeunload и в способе кроссбраузерности библиотека PageLifecycle. js является нашим рекомендуемым решением.

Со страницы API жизненного цикла страницы.

...