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。但是在第一页上,我们设置了两个 unloadbeforeunload 处理程序。如果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);

如果onbeforeunloadwindow 的属性,则警报为“真”(即使它为空)。

这应该做同样的事情:

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 视图(移动)

JS捕获关闭浏览器事件之chrome浏览器真支持onbeforeunload事件吗

如何在 Safari 上使用 JS 检测用户关闭页面