【问题标题】:onbeforeunload support detectiononbeforeunload 支持检测
【发布时间】:2008-10-01 17:08:28
【问题描述】:

我想检查当前浏览器是否支持 onbeforeunload 事件。 执行此操作的常用 javascript 方法似乎不起作用:

if (window.onbeforeunload) {
    alert('yes');
}
else {
    alert('no');
}

实际上,它只检查是否某个处理程序已附加到事件。 有没有办法在不检测特定浏览器名称的情况下检测是否支持 onbeforeunload?

【问题讨论】:

    标签: javascript


    【解决方案1】:

    前段时间我在现代浏览器中写了一个或多或少的reliable inference for detecting event support。您可以在演示页面上看到至少 Safari 4+、FF3.x+ 和 IE 支持“beforeunload”。

    编辑:这种技术现在用于 jQuery、Prototype.js、Modernizr 以及可能的其他脚本和库。

    【讨论】:

    【解决方案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 对这些功能的实现。

            【讨论】:

              猜你喜欢
              • 2011-07-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-04-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多