onbeforeunload 支持检测
Posted
技术标签:
【中文标题】onbeforeunload 支持检测【英文标题】:onbeforeunload support detection 【发布时间】:2008-10-01 17:08:28 【问题描述】:我想检查当前浏览器是否支持 onbeforeunload 事件。 执行此操作的常用 javascript 方法似乎不起作用:
if (window.onbeforeunload)
alert('yes');
else
alert('no');
实际上,它只检查是否某个处理程序已附加到事件。 有没有办法在不检测特定浏览器名称的情况下检测是否支持 onbeforeunload?
【问题讨论】:
【参考方案1】:前段时间我在现代浏览器中写了一个或多或少的reliable inference for detecting event support。您可以在演示页面上看到至少 Safari 4+、FF3.x+ 和 IE 支持“beforeunload”。
编辑:这种技术现在用于 jQuery、Prototype.js、Modernizr 以及可能的其他脚本和库。
【讨论】:
上方链接的网站是否已关闭?对我不起作用,但我找到了cached version。 警告:我在@kangax's page 上写了一条评论,特别是关于onbeforeunload
在移动Safari 上被检测为支持,即使它actually doesn't work reliably。【参考方案2】:
很遗憾,kangax's answer 不适用于 Safari on ios。在我的测试中,我尝试过的所有浏览器都支持beforeunload
,除了IOS上的Safari :-(
相反,我建议采用不同的方法:
这个想法很简单。在第一次访问页面时,我们实际上还不知道是否
支持beforeunload
。但是在第一页上,我们设置了两个
unload
和 beforeunload
处理程序。如果beforeunload
处理程序触发,我们设置一个
表示支持beforeunload
的标志(实际上是beforeunloadSupported =
"yes"
)。当unload
处理程序触发时,如果尚未设置标志,我们设置
标记beforeunload
不支持。
下面我们将使用localStorage
(在我关心的所有浏览器中都支持
about - 请参阅 http://caniuse.com/namevalue-storage )以获取/设置标志。我们
也可以使用 cookie,但我选择了localStorage
,因为那里
没有理由在每次请求时将此信息发送到 Web 服务器。我们
只需要一个可以在页面重新加载后幸存的标志。一旦我们检测到它,它就会
永远保持检测状态。
有了这个,你现在可以打电话给isBeforeunloadSupported()
,它会告诉你。
(function($)
var field = 'beforeunloadSupported';
if (window.localStorage &&
window.localStorage.getItem &&
window.localStorage.setItem &&
! window.localStorage.getItem(field))
$(window).on('beforeunload', function ()
window.localStorage.setItem(field, 'yes');
);
$(window).on('unload', function ()
// If unload fires, and beforeunload hasn't set the field,
// then beforeunload didn't fire and is therefore not
// supported (cough * iPad * cough)
if (! window.localStorage.getItem(field))
window.localStorage.setItem(field, 'no');
);
window.isBeforeunloadSupported = function ()
if (window.localStorage &&
window.localStorage.getItem &&
window.localStorage.getItem(field) &&
window.localStorage.getItem(field) == "yes" )
return true;
else
return false;
)(jQuery);
这是完整的jsfiddle 示例用法。
请注意,它只会在您网站的第二次或任何后续页面加载时检测到。如果让它在第一页上工作对您来说也很重要,您可以在该页面上加载一个 iframe
并在该页面上加载一个 src
属性,该属性指向同一域上的一个页面,并在此处进行检测,确保它具有加载,然后将其删除。这应该确保检测已经完成,所以isBeforeunloadSupported()
甚至可以在第一页上工作。但我不需要那个,所以我没有把它放在我的演示中。
【讨论】:
【参考方案3】:我意识到我在这个方面有点晚了,但我现在正在处理这个问题,我想像下面这样的东西会更容易、更可靠。这是 jQuery 特有的,但它应该适用于任何允许绑定和取消绑定事件的系统。
$(window).bind('unload', function()
alert('unload event');
);
window.onbeforeunload = function()
$(window).unbind('unload');
return 'beforeunload event';
如果beforeunload
事件触发,这应该解除unload
事件的绑定。否则它只会触发卸载。
【讨论】:
【参考方案4】:alert('onbeforeunload' in window);
如果onbeforeunload
是window
的属性,则警报为“真”(即使它为空)。
这应该做同样的事情:
var supportsOnbeforeunload = false;
for (var prop in window)
if (prop === 'onbeforeunload')
supportsOnbeforeunload = true;
break;
alert(supportsOnbeforeunload);
最后:
alert(typeof window.onbeforeunload != 'undefined');
同样,typeof window.onbeforeunload
似乎是“对象”,即使它当前具有值 null
,所以这是可行的。
【讨论】:
在 IE、Opera 和 Safari 中几乎可以正常工作,但 FF 给我错误,这似乎不正确 抱歉,我认为它工作可靠,因为我没有意识到 Firefox 支持 onbeforeunload。 Firefox 不支持这种推断,但允许在元素上设置相应属性时检测“beforeunload”。 var el = document.createElement('div'); el.setAttribute('onbeforeunload', ''); typeof el.onbeforeunload; // “函数” 这在 iOS Safari 中对我不起作用。即使不支持,它也会说支持 beforeunload 事件【参考方案5】:地壳,
DOM-Events 规范中没有定义“beforeunload”,这是 IE 特有的功能。我认为创建它是为了在标准“卸载”事件之前触发执行。在其他 IE 浏览器中,您可以使用捕获阶段“卸载”事件侦听器,从而在例如内联正文 onunload 事件之前执行代码。
另外,DOM 不提供任何接口来测试其对特定事件的支持,您只能测试对事件组(MouseEvents、MutationEvents 等)的支持
同时你也可以参考 DOM-Events 规范http://www.w3.org/TR/DOM-Level-3-Events/events.html(可惜IE不支持)
希望这些信息对一些人有所帮助
【讨论】:
谢谢哥们,但这只是理论 - 看看这个问题的其他答案,你会找到几乎完美的解决方案。所以,我真的不在乎 DOM 是否提供了一些接口。实际上,有可靠的方法来检查它,这很重要。哦,顺便说一句,只有 Opera 缺乏支持。【参考方案6】:不同方法,获取typeof
if(typeof window.onbeforeunload == 'function')
alert("hello functionality!");
【讨论】:
你测试的是什么浏览器? 所有这些,IE,Opera,Safari,Firefox 如果(typeof window.onbeforeunload != 'undefined') 关闭,但在 FF 中失败,您的代码在任何浏览器中都不起作用【参考方案7】:FF 也支持 onbeforeunload,因此对浏览器的测试无济于事。
【讨论】:
【参考方案8】:手机浏览器不会倾向于不支持beforeunload
,因为浏览器可以在不卸载页面的情况下进入后台,然后随时被操作系统杀死。
但是,所有现代非移动浏览器都支持它。因此,您只需检查浏览器是否为移动浏览器即可。
解决我使用的问题:
var isMobile = navigator.userAgent.match(/android/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/iPhone|iPad|iPod/i) || navigator.userAgent.match(/Opera Mini/i) || navigator.userAgent.match(/IEMobile/i);
if (isMobile)
window.addEventListener("visibilitychange", function(e)
if (document.visibilityState == 'hidden')
console.log("beforeunload");
location.reload();
);
else
window.addEventListener("beforeunload", function(e)
console.log("beforeunload");
);
【讨论】:
【参考方案9】:我看到这是一个非常古老的线程,但接受的答案错误地检测到 iOS 上对 Safari 的支持,这导致我调查其他策略:
if ('onbeforeunload' in window && typeof window['onbeforeunload'] === 'function')
// onbeforeunload is supported
else
// maybe bind to unload as a last resort
if-check 的第二部分对于 iOS 上的 Safari 是必需的,它的属性设置为 null
。
在 Chrome 37、IE11、Firefox 32 和适用于 iOS 7.1 的 Safari 中测试
【讨论】:
onbeforeunload
默认情况下始终设置为 null。如果您设置onbeforeunload
函数,它将始终是一个函数。这并不意味着它会被触发。我没有你测试过的东西,但这行不通。这里唯一的方法是 iOS 设备检测或 Peter V. Mørch 的方法。【参考方案10】:
最好手动找出哪些浏览器支持它,然后让你的条件更像:
if( $.browser.msie )
alert( 'no' );
...等等。
$.browser.msie
是 jQuery 语法,大多数框架都有类似的内置函数,因为它们在内部使用了很多。如果您不使用框架,那么我建议您看看 jQuery 对这些功能的实现。
【讨论】:
以上是关于onbeforeunload 支持检测的主要内容,如果未能解决你的问题,请参考以下文章
使用onbeforeunload事件检测窗口是否刷新或关闭 .
JavaScript 问题:Onbeforeunload 还是 Onunload?
Facebook Messenger 检测关闭 web 视图(移动)