有啥方法可以在 iOS 设备的 Mobile Safari 上使用 window.onbeforeunload 吗?
Posted
技术标签:
【中文标题】有啥方法可以在 iOS 设备的 Mobile Safari 上使用 window.onbeforeunload 吗?【英文标题】:Is there any way to use window.onbeforeunload on Mobile Safari for iOS devices?有什么方法可以在 iOS 设备的 Mobile Safari 上使用 window.onbeforeunload 吗? 【发布时间】:2011-05-06 20:54:35 【问题描述】:Apple 似乎已禁用 ios 设备(iPhone、iPad、iPod Touch)的 window.onbeforeunload 事件。不幸的是,我找不到任何文档说明为什么此事件在 Mobile Safari 中不起作用。
有谁知道这个功能是否有可靠的替代品? android 的浏览器似乎支持它就好了,Safari 桌面应用程序也毫无问题地支持 onbeforeunload 事件。
【问题讨论】:
这是window.onbeforeunload not working on the iPad?的副本 这能回答你的问题吗? window.onbeforeunload not working on the iPad? 【参考方案1】:我看到这是一个老问题,但我最近遇到了这个问题。
我正在使用 window.unload
,它在 ios 浏览器中运行良好(尽管如果您查看 Apple documentation,它似乎已被弃用,他们建议使用 document.pagehide
)
【讨论】:
当用户重新加载页面时,页面隐藏和卸载似乎都无法在 iOS 9 上运行。 那么...我们应该使用什么? :)【参考方案2】:如果你真的需要它,你不能只获取所有链接、表单和 DOM 对象,它们有一个处理程序更改 url 并让它们等到你完成了你想要的。 对于链接,您可以通过 getElementsByTagName 获取它们,检查 href 是否以除 # 以外的任何内容开头,然后添加您的 onbeforeunload 函数 add onclick(将在查看 href 之前调用该函数)。 表单相同,但有 onsubmit。 最后,对于使用 javascript 更改 href 的元素,您应该确保在添加调用 onbeforeunlaod 函数的 lsitener 时(或者,如果您使用 DOM0 或 DOM1 侦听器,您可以添加一些类,然后使用全局脚本使用类检查所有元素并将其添加到带有闭包的事件侦听器中。
但是您通常应该能够避免使用此事件(可能使用 cookie 来存储您希望每 x 秒发送一次的内容,并且在最坏的情况下允许在下次用户加载时查看它一个页面,在最好的情况下,能够在 onbeforeunload 或 onunload 发送一个 Ajax 请求,即使它只发送 http 标头,也可以让你得到你想要的)。
【讨论】:
感谢 Xavier,所有的可能性,但这些都需要大量的 DOM 修改,对于我的应用程序来说这是不切实际的,因为它可能会干扰托管页面的功能。 您不需要在每个链接上添加事件等等,您可以使用事件委托。你可以把一个放在身体上并使用 e.srcElement || e.target 然后检查它是否会更改网址。这样,您不需要放置那么多元素。但是您可能仍然需要将 onsubmit 放在自己的表单上...不确定。 对于用户实际关闭页面而不是通过元素移动到另一个页面的场景的任何选项? 不。如果它在计算机上,您可以检测到鼠标离开窗口并做好准备。最好的办法可能是一直告诉服务器“我还在这里”,这样它就可以推断出你没有离开,所以设置服务器超时。最好使用 websockets 而不是许多 Ajax 调用。除此之外,我唯一能想到的就是总是强迫用户也有一些专注于在 onblur 发送消息(并且可能在它之后添加一点点真实)。无论如何,如果不惹恼用户,您将无法使用任何东西。【参考方案3】:根据 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);
此解决方案有一些限制。最大的一个是它附加到所有表单和所有链接。有时这可能不是所希望的。如果需要,可以跳过一些节点(例如,用特定的 data-
属性标记它们)。
【讨论】:
【参考方案4】:我遇到了同样的问题。似乎 iphone 中的 safari 浏览器仅触发焦点和模糊事件,几乎所有其他事件都没有触发,例如(页面隐藏、页面显示、可见性更改),但好消息是焦点和模糊事件在 iphone、ipad 和 Android 手机上得到支持和触发也是。
window.addEventListener('focus', function()
// do stuff
);
window.addEventListener('blur', function()
// do stuff
);
希望这对任何人都有帮助。
【讨论】:
以上是关于有啥方法可以在 iOS 设备的 Mobile Safari 上使用 window.onbeforeunload 吗?的主要内容,如果未能解决你的问题,请参考以下文章
目前有啥方法可以在装有 iOS 9 的 iOS 设备上浏览 App 文件夹/App Sandbox
iOS(Apple):应用程序有啥方法可以要求操作系统阻止该应用程序中的设备?
当我的 iOS 开发者帐户中有超过 100 台设备时,有啥方法可以添加更多 UDID?
T-Mobile G1(品牌 HTC Dream)和 Google 的 ADP1(开发者设备)有啥区别?
iOS - pod 'Google-Mobile-Ads-SDK' 和 pod 'Firebase/AdMob' 有啥区别