Есть ли способ использовать window.onbeforeunload на Mobile Safari для устройств iOS?

Похоже, Apple отключила событие window.onbeforeunload для устройств iOS (iPhone, iPad, iPod Touch). К сожалению, я не могу найти документацию о том, почему это событие не работает в Mobile Safari.

Кто-нибудь знает, есть ли надежная альтернатива этой функции? Браузер Android, похоже, прекрасно его поддерживает, а настольное приложение Safari также поддерживает событие onbeforeunload без проблем.

2 ответа

Я вижу, что это старый вопрос, но я недавно столкнулся с этой проблемой.

я использую window.unload и он отлично работает в браузерах IOS (хотя, если вы посмотрите на документацию Apple, она устарела, и они рекомендуют использовать document.pagehide)

Основываясь на ответе Ксавьера, я разработал решение в этом направлении:

function doStuff() {
  // here goes your logic
}

function isSafariMobile() {
  return navigator && /Safari/.test(navigator.userAgent) && /iPhone|iPad/.test(navigator.userAgent)
}

function addWatcherToLinks(baseNode) {
  if (!baseNode || !baseNode.querySelectorAll) { return; } // ignore comments, text, etc.
  for (const link of baseNode.querySelectorAll("a")) {
    link.addEventListener('click', doStuff);
  }
  for (const form of baseNode.querySelectorAll("form")) {
    form.addEventListener('submit', doStuff);
  }
}

// ...when the page loads...
// we watch the page for beforeunload to call doStuff
// Since Safari mobile does not support this, we attach a listener (watcher) to each link and form and then call doStuff.
// Also, we add such a watcher to all new incoming nodes (DOMNodeInserted).
if (isSafariMobile()) {
  addWatcherToLinks(document);
  window.addEventListener("DOMNodeInserted", (event) => { addWatcherToLinks(event.target); }, false);
} else {
  window.addEventListener('beforeunload', doStuff);
}

У этого решения есть некоторые ограничения. Самый большой из них заключается в том, что он прикрепляется ко всем формам и всем ссылкам. Иногда это может быть нежелательно. Если вам это нужно, вы можете пропустить некоторые узлы (например, пометить их определеннымdata- атрибут).

Если вам это действительно нужно, вы не можете просто получить все ссылки, формы и DOM-объекты, у которых есть обработчик, изменяющий URL-адрес, и заставить их ждать, пока вы не сделаете то, что хотите. Для ссылок вы получите их с помощью getElementsByTagName, проверьте, начинается ли href с чего-либо, кроме #, и просто добавьте свою функцию onbeforeunload add onclick (которая будет вызвана до того, как href будет просматриваться). То же самое для форм, но с отправкой. И наконец, для элементов, изменяющих href с помощью JavaScript, вы должны убедиться, что при добавлении lsitener, который вы вызываете своей функцией onbeforeunlaod (или, если вы используете прослушиватели DOM0 или DOM1, вы можете просто добавить некоторый класс и затем использовать глобальный скрипт это проверяет все элементы с классом и добавляет его к слушателю события с закрытием.

Но, как правило, вы должны избегать использования этого события (возможно, с помощью файлов cookie для хранения того, что вы хотите отправлять каждые x секунд, и, в худшем случае, для просмотра его в следующий раз, когда пользователь загружает страницу и в лучшем случае сможет отправлять Ajax-запрос при onbeforeunload или onunload, который, даже если он отправляет только заголовки http, позволит вам получить то, что вы хотите).

У меня была такая же проблема. Кажется, что браузер сафари в iphone запускает только события фокусировки и размытия, и почти каждое другое событие не запускается, например (pagehide, pageshow, изменение видимости), но хорошие новости заключаются в том, что событие фокусировки и размытия поддерживается и запускается на мобильных устройствах iphone, ipad и android также.

    window.addEventListener('focus', function(){
       // do stuff
     });

   window.addEventListener('blur', function(){
       // do stuff
     });

надеюсь, что это поможет кому-нибудь.

Другие вопросы по тегам