检测对给定 JavaScript 事件的支持?

IT技术 javascript dom-events progressive-enhancement
2021-03-04 17:05:32

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

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

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

4个回答

好吧,最好的方法不是通过浏览器嗅探,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;'是否自动转换为函数。
2021-04-19 17:05:32
@BlueRaja,我只是提到 jQuery 作为参考,一个严肃的库依赖于这种技术。
2021-05-06 17:05:32
此方法不适用于 'onhashchange' 事件。该函数有一个缺陷,它会错过任何仅附加到 window 对象的事件。此外,我相信将 "'hashchange':'window'" 添加到 TAGNAMES 列表是没有意义的,因为无法创建新的窗口元素。使用“isEventSupported('hashchange')”,createElement() 函数将返回一个没有 onhashchange 事件作为属性的 div,因此即使 window.onhashchange 可能为真,测试也会失败。
2021-05-11 17:05:32
@CMS - 您还应该添加前缀检查
2021-05-16 17:05:32

Mozilla的文件提出以下建议:

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

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

十分优雅。我可能会使用一个修改过的版本,其中包含来自发布的其他答案的一些想法。谢谢。
2021-04-20 17:05:32

这是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事件类进行简单检查有什么问题(见我的回答
2021-04-27 17:05:32

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

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