扫码关注官方订阅号
比如musewheel事件,如何检测在当前浏览器的实现中是否可以使用? 如果使用类似document.onmousewheel这样的方式,如何避免这个方法被人恶意(重)定义?
小伙看你根骨奇佳,潜力无限,来学PHP伐。
楼上的给出了一段封装好的代码,我尝试讲一下思路什么的。
在大多数的现代浏览器中,你可以通过下面的方式检测在当前浏览器中是否可以用这个事件:
'onclick' in document.documentElement;
嗯,前面说了这段代码只是在大多数浏览器中可用,并不是所有的浏览器中都靠谱。为什么,因为可能会用到一些偏门的事件,比如只有IE支持的mouseenter,mouseleave,onpropertychange什么的,IE9-中没有oninput事件什么的,或者还有一些其他浏览器中才有的事件等等。这本身就取决于浏览器对标准的实现,和自身的实现。
mouseenter
mouseleave
onpropertychange
oninput
经评论中@依云的补充,测试发现现代浏览器都兼容了mouseenter,mouseleave事件。
上面这种方法不靠谱,那就另辟蹊径,尽量进行可靠的测试。比如reset事件通常用于表单重置操作,事实上在某些浏览器下面直接检测document.documentElement - 文档是否支持的时候可能不同的浏览器结果不同。而这个时候可以尝试检测特定的元素是否支持这个事件。毕竟可以粗略的说,在浏览器中事件大部分情况都是用在DOM元素上的。因此,可以还可以这样检测:
reset
document.documentElement
DOM
'onreset' in document.createElement('input')
通常情况下直接尝试查看浏览器的event属性的类型会发现它会返回字符串'function',便于测试,还可以这样:
event
'function'
var dom = document.createElement('p'); dom.setAttribute('onclick', 'xxx'); // 保险起见,设置浏览器可能已知的事件类型来测试它 typeof dom.onclick; // -> 'function',测试浏览器已知事件类型的时候通常覆写没用,它会正确的返回内置属性 // 也可以换个自定义的事件使用这种方式尝试检测
根据上面这些结论,就可以定义一个通用的函数来检测浏览器是否支持特定的事件了:
function detectEventSupport(eventName) { var tempElement = document.createElement('p'), isSupported; eventName = 'on' + eventName; isSupported = (eventName in tempElement); // 使用第一种方式 // 如果第一种方式行不通,那就来看看它是不是已知事件类型 if(!isSupported) { tempElement.setAttribute(eventName, 'xxx'); isSupported = typeof tempElement[eventName] === 'function'; } // 清除掉动态创建的元素,以便内存回收 tempElement = null; // 返回检测结果 return isSupported; }
至此,一个基本靠谱的测试函数就完备了。
楼上的代码中有个TAGNAMES,然后在后面的检测中用到了。这里实际上只是为了保证测试的完备性和健壮性,列出了一部分已知在这些元素上支持的事件进行测试。
TAGNAMES
写在最后,正如上面所说。因为可能会用到某些浏览器厂商自定义的事件类型什么的,这种情况下最好查查规范,查查浏览器相关的文档,以确保测试的准确性。而对于多数标准的浏览器事件,上面的方法是能够进行可靠检测的。万一碰到无法确认的,查文档;针对特定的环境进行检测即可,思路有了就好办了。
补充修正:
document
p
key in object
document.onxxx = 'xxx'; 'onxxx' in document;
这种情况下key in object就显得不那么可靠了。
解释下上面第三种方式,为什么先setAttribute,再用ele[eventName]的方式检测。在标准中规定,使用setAttribute()方法添加已有的属性时会重写指定的属性值。但是事实上,在用这个方法设置已有的事件属性时,然后直接用ele[eventName]访问这个属性,始终返回的是已有的事件属性,而事件属性对应的实现都是function。
setAttribute
ele[eventName]
setAttribute()
function
因而基于这种方式,检测已知事件属性类型时总是返回'function'。
先回答前一个问题。
可以参考Modernizr的处理方式:
function is( obj, type ) { return typeof obj === type; } var isEventSupported = (function() { var TAGNAMES = { 'select': 'input', 'change': 'input', 'submit': 'form', 'reset': 'form', 'error': 'img', 'load': 'img', 'abort': 'img' }; function isEventSupported( eventName, element ) { element = element || document.createElement(TAGNAMES[eventName] || 'p'); eventName = 'on' + eventName; var isSupported = eventName in element; if ( !isSupported ) { if ( !element.setAttribute ) { element = document.createElement('p'); } if ( element.setAttribute && element.removeAttribute ) { element.setAttribute(eventName, ''); isSupported = is(element[eventName], 'function'); if ( !is(element[eventName], 'undefined') ) { element[eventName] = undefined; } element.removeAttribute(eventName); } } element = null; return isSupported; } return isEventSupported; })();
isEventSupported("mousewheel")// Chrome -> true isEventSupported("mousewheel")// Firefox -> false
微信扫码关注PHP中文网服务号
QQ扫码加入技术交流群
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
PHP学习
技术支持
返回顶部
楼上的给出了一段封装好的代码,我尝试讲一下思路什么的。
在大多数的现代浏览器中,你可以通过下面的方式检测在当前浏览器中是否可以用这个事件:
嗯,前面说了这段代码只是在大多数浏览器中可用,并不是所有的浏览器中都靠谱。为什么,因为可能会用到一些偏门的事件,比如只有IE支持的
mouseenter,mouseleave,onpropertychange什么的,IE9-中没有oninput事件什么的,或者还有一些其他浏览器中才有的事件等等。这本身就取决于浏览器对标准的实现,和自身的实现。上面这种方法不靠谱,那就另辟蹊径,尽量进行可靠的测试。比如
reset事件通常用于表单重置操作,事实上在某些浏览器下面直接检测document.documentElement- 文档是否支持的时候可能不同的浏览器结果不同。而这个时候可以尝试检测特定的元素是否支持这个事件。毕竟可以粗略的说,在浏览器中事件大部分情况都是用在DOM元素上的。因此,可以还可以这样检测:通常情况下直接尝试查看浏览器的
event属性的类型会发现它会返回字符串'function',便于测试,还可以这样:根据上面这些结论,就可以定义一个通用的函数来检测浏览器是否支持特定的事件了:
至此,一个基本靠谱的测试函数就完备了。
楼上的代码中有个
TAGNAMES,然后在后面的检测中用到了。这里实际上只是为了保证测试的完备性和健壮性,列出了一部分已知在这些元素上支持的事件进行测试。写在最后,正如上面所说。因为可能会用到某些浏览器厂商自定义的事件类型什么的,这种情况下最好查查规范,查查浏览器相关的文档,以确保测试的准确性。而对于多数标准的浏览器事件,上面的方法是能够进行可靠检测的。万一碰到无法确认的,查文档;针对特定的环境进行检测即可,思路有了就好办了。
补充修正:
document对象或者p元素进行测试,可能需要处理的元素并不是p,那么针对特定的元素进行处理即可。key in object的方式进行检测的时候很容易受自定义事件的影响,比如:这种情况下
key in object就显得不那么可靠了。解释下上面第三种方式,为什么先
setAttribute,再用ele[eventName]的方式检测。在标准中规定,使用setAttribute()方法添加已有的属性时会重写指定的属性值。但是事实上,在用这个方法设置已有的事件属性时,然后直接用ele[eventName]访问这个属性,始终返回的是已有的事件属性,而事件属性对应的实现都是function。因而基于这种方式,检测已知事件属性类型时总是返回
'function'。先回答前一个问题。
可以参考Modernizr的处理方式: