【问题标题】:Detecting support for a given JavaScript event?检测对给定 JavaScript 事件的支持?
【发布时间】:2010-05-20 20:04:15
【问题描述】:

我有兴趣使用 JavaScript hashchange 事件来监控 URL 片段标识符的变化。我知道Really Simple History 和为此的jQuery 插件。但是,我得出的结论是,在我的特定项目中,增加另一个 JS 文件的开销并不值得。

我想做的是走“渐进式增强”路线。也就是说,我想测试访问者的浏览器是否支持 hashchange 事件,并编写我的代码以使用它(如果它可用),作为增强而不是核心功能。 IE 8、Firefox 3.6 和 Chrome 4.1.249 都支持它,这约占我网站流量的 20%。

那么,呃……有什么方法可以测试浏览器是否支持特定事件?

【问题讨论】:

  • 仅供参考,您正在寻找的短语不是“渐进式增强”而是“优雅降级”。渐进式增强是指您让所有用户都可以访问您的网站,但向更具体的用户组添加功能(启用 JavaScript、支持 HTML5 等)。优雅降级是指您依赖于某些功能,但如果客户端不支持,则有备份方法。并不是说它真的很重要。 :)
  • 嗯。我认为“优雅降级”意味着网站继续运行,即使它通常依赖的功能不可用。相比之下,“渐进式增强”是指站点启用它不依赖的额外功能,仅当用户代理支持它们时。我计划以这样一种方式编写此特定代码,即它根本不会修改 location.hash 属性,除非 hashchange 事件可用。所以这是一个渐进的增强。是的,这并不重要——它们只是一枚硬币的两个面。

标签: javascript dom-events progressive-enhancement


【解决方案1】:

好吧,最好的方法不是通过浏览器嗅探,Juriy Zaytsev (@kangax) 提出了一种非常有用的检测事件支持的方法:

var isEventSupported = (function(){
  var TAGNAMES = {
    'select':'input','change':'input',
    'submit':'form','reset':'form',
    'error':'img','load':'img','abort':'img'
  }
  function isEventSupported(eventName) {
    var el = document.createElement(TAGNAMES[eventName] || 'div');
    eventName = 'on' + eventName;
    var isSupported = (eventName in el);
    if (!isSupported) {
      el.setAttribute(eventName, 'return;');
      isSupported = typeof el[eventName] == 'function';
    }
    el = null;
    return isSupported;
  }
  return isEventSupported;
})();

用法:

if (isEventSupported('hashchange')) {
  //...
}

这种技术现在在一些库中使用,例如 jQuery

在这里阅读更多:

【讨论】:

  • 这是一个非常有趣的方法...我特别喜欢查看'return;'是否自动转换为函数的额外检查。
  • @BlueRaja,我只是提到 jQuery 作为参考,一个严肃的库依赖于这种技术。
  • 此方法不适用于 'onhashchange' 事件。该函数有一个缺陷,它会错过仅附加到窗口对象的任何事件。此外,我相信,将“'hashchange':'window'” 添加到 TAGNAMES 列表中是没有意义的,因为无法创建新的窗口元素。使用“isEventSupported('hashchange')”,createElement() 函数将返回一个不具有 onhashchange 事件作为属性的 div,因此即使 window.onhashchange 可能为真,测试也会失败。
  • @CMS - 你也应该添加前缀检查
【解决方案2】:

Mozilla documentation 建议如下:

if ("onhashchange" in window) {
    alert("The browser supports the hashchange event!");
}

这也适用于 IE8 和 Chrome 5 beta(我没有测试 Chrome 4.1),并且在 Opera 和 Safari 中正确失败。

【讨论】:

  • 非常优雅。我可能会使用这个修改过的版本,其中包含来自发布的其他答案的一些想法。谢谢。
【解决方案3】:

这是对answer provided by CMS 的修改,它不包含另一个函数,我认为它可以工作:

function event_exists(eventName){
    if(typeof(eventName)!='string' || eventName.length==0)return false;
    var TAGNAMES = {
        'select':'input','change':'input',
        'submit':'form','reset':'form',
        'error':'img','load':'img','abort':'img'
    }
    var el = document.createElement(TAGNAMES[eventName] || 'div');
    eventName = 'on' + eventName;
    var isSupported = (eventName in el);
    if (!isSupported) {
        el.setAttribute(eventName,'return;');
        isSupported = (typeof(el[eventName])=='function');
    }
    el = null;
    return isSupported;
}

【讨论】:

  • 为什么需要创建一个新元素?仅对事件类进行简单的typeof 检查有什么问题? (见my answer
【解决方案4】:

我认为最简单的解决方案是对事件类进行typeof 检查。

例如:typeof(InputEvent) 在 Chrome 中返回 "function",在 Internet Explorer 中返回 "undefined"

【讨论】:

    猜你喜欢
    • 2013-09-29
    • 2012-06-08
    • 2010-12-25
    • 1970-01-01
    • 2011-06-01
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多