Javascript 有没有办法在 iOS 设备的 Mobile Safari 上使用 window.onbeforeunload?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4127621/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there any way to use window.onbeforeunload on Mobile Safari for iOS devices?
提问by 8three
Looks like Apple has disabled the window.onbeforeunload event for iOS devices (iPhone, iPad, iPod Touch). Unfortunately I can't find any documentation as to why this event doesn't work in Mobile Safari.
看起来苹果已经禁用了 iOS 设备(iPhone、iPad、iPod Touch)的 window.onbeforeunload 事件。不幸的是,我找不到任何关于为什么此事件在 Mobile Safari 中不起作用的文档。
Does anyone know if there's a reliable alternative to this function? Android's browser appears to support it just fine, and the Safari desktop application also supports the onbeforeunload event without issue.
有谁知道这个功能是否有可靠的替代方案?Android 的浏览器似乎很好地支持它,而 Safari 桌面应用程序也支持 onbeforeunload 事件而没有问题。
回答by Miquel
I see that it's an old question, but i faced this problem recently.
我看到这是一个老问题,但我最近遇到了这个问题。
I'm using window.unload
and it works fine in ios browsers (although if you look at Apple documentationit seems to be deprecated and they recommend to use document.pagehide
)
我正在使用window.unload
并且在 ios 浏览器中运行良好(尽管如果您查看Apple 文档,它似乎已被弃用,他们建议使用document.pagehide
)
回答by xavierm02
If you really need it, you cant just get all links, forms and DOM objects that have a handler changing the url and make those wait until you've done what you want. For the links, you get them by getElementsByTagName, check if the href starts with anything but a # and just add your onbeforeunload function add onclick (which will be invoked before the href is looked at). Same for the forms but with onsubmit. And finaly, for the elements changing the href with JavaScript, you should make sure when you add the lsitener that you call your onbeforeunlaod function (or, if you use DOM0 or DOM1 listeners, you can just add some class and then use a global script that checks all elements with the class and adds it to the event listener with a closure.
如果您真的需要它,您不能只获取所有具有更改 url 的处理程序的链接、表单和 DOM 对象,并让它们等到您完成您想要的操作。对于链接,您可以通过 getElementsByTagName 获取它们,检查 href 是否以 # 以外的任何内容开头,然后添加您的 onbeforeunload 函数 add onclick(将在查看 href 之前调用)。表单相同,但带有 onsubmit。最后,对于使用 JavaScript 更改 href 的元素,您应该确保在添加调用 onbeforeunlaod 函数的 lsitener 时(或者,如果您使用 DOM0 或 DOM1 侦听器,则可以添加一些类,然后使用全局脚本使用该类检查所有元素,并使用闭包将其添加到事件侦听器中。
But you should normaly be able to avoid the use of this event (probably using cookies to store the thing you wanted to send every x seconds and allowing to, in the worst case, have a look at it next time the user loads a page and, in the best case, be able to send an Ajax request at onbeforeunload or onunload which, even if it sends only the http headers, woudl allow you to get what you want).
但是您通常应该能够避免使用此事件(可能使用 cookie 来存储您想要每 x 秒发送一次的内容,并允许在最坏的情况下,在用户下次加载页面时查看它并,在最好的情况下,能够在 onbeforeunload 或 onunload 发送 Ajax 请求,即使它只发送 http 标头,也可以让你得到你想要的)。
回答by Motine
Based on Xavier's answer, I devised a solution along these lines:
根据 Xavier 的回答,我设计了一个解决方案:
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);
}
This solution has some limitations. The biggest one is that it attaches itself to allforms and all links. Sometimes this might not be desired. If you need it you can skip some nodes (e.g. mark them with a particular data-
attribute).
此解决方案有一些限制。最大的一个是它依附于所有形式和所有链接。有时这可能不是所希望的。如果您需要它,您可以跳过一些节点(例如用特定data-
属性标记它们)。