一般我们在JS中添加事件,是这样子的




​1​

​obj.onclick=method​


这种绑定事件的方式,兼容主流浏览器,但如果一个元素上添加多次同一事件呢?




​1​

​obj.onclick=method1;​


​2​

​obj.onclick=method2;​


​3​

​obj.onclick=method3;​


如果这样写,那么只有最后绑定的事件,这里是method3会被执行,这个时候我们就不能用onclick这样的写法了,主角改登场了,在IE中我们可以使用attachEvent方法




​1​

​//object.attachEvent(event,function);​


​2​

​btn1Obj.attachEvent(​​​​"onclick"​​​​,method1);​


​3​

​btn1Obj.attachEvent(​​​​"onclick"​​​​,method2);​


​4​

​btn1Obj.attachEvent(​​​​"onclick"​​​​,method3);​


使用格式是前面是事件类型,注意的是需要加on,比如onclick,onsubmit,onchange,执行顺序是

method3->method2->method1

可惜这个微软的私人方法,火狐和其他浏览器都不支持,幸运的是他们都支持W3C标准的addEventListener方法




​1​

​//element.addEventListener(type,listener,useCapture);​


​2​

​btn1Obj.addEventListener(​​​​"click"​​​​,method1,​​​​false​​​​);​


​3​

​btn1Obj.addEventListener(​​​​"click"​​​​,method2,​​​​false​​​​);​


​4​

​btn1Obj.addEventListener(​​​​"click"​​​​,method3,​​​​false​​​​);​


执行顺序为method1->method2->method3

做前端开发工程师,最悲剧的某过于浏览器兼容问题了,上面有两种添加事件的方法,为了同一添加事件的方法,我们不得不再重新写一个通用的添加事件函数,幸亏再有前人帮我们做了这件事




​01​

​function​​ ​​addEvent(elm, evType, fn, useCapture) {​


​02​

​if​​ ​​(elm.addEventListener) {​


​03​

​elm.addEventListener(evType, fn, useCapture);​​​​//DOM2.0​


​04​

​return​​ ​​true​​​​;​


​05​

​}​


​06​

​else​​ ​​if​​ ​​(elm.attachEvent) {​


​07​

​var​​ ​​r = elm.attachEvent(‘on‘ + evType, fn);​​​​//IE5+​


​08​

​return​​ ​​r;​


​09​

​}​


​10​

​else​​ ​​{​


​11​

​elm[​​​​'on'​​ ​​+ evType] = fn;​​​​//DOM 0​


​12​

​}​


​13​

​}​


下面是Dean Edwards 的版本




​01​

​function​​ ​​addEvent(element, type, handler) {​


​02​

​//为每一个事件处理函数分派一个唯一的ID​


​03​

​if​​ ​​(!handler.$$guid) handler.$$guid = addEvent.guid++;​


​04​

​//为元素的事件类型创建一个哈希表​


​05​

​if​​ ​​(!element.events) element.events = {};​


​06​

​//为每一个"元素/事件"对创建一个事件处理程序的哈希表​


​07​

​var​​ ​​handlers = element.events[type];​


​08​

​if​​ ​​(!handlers) {​


​09​

​handlers = element.events[type] = {};​


​10​

​//存储存在的事件处理函数(如果有)​


​11​

​if​​ ​​(element[​​​​"on"​​ ​​+ type]) {​


​12​

​handlers[0] = element[​​​​"on"​​ ​​+ type];​


​13​

​}​


​14​

​}​


​15​

​//将事件处理函数存入哈希表​


​16​

​handlers[handler.$$guid] = handler;​


​17​

​//指派一个全局的事件处理函数来做所有的工作​


​18​

​element[​​​​"on"​​ ​​+ type] = handleEvent;​


​19​

​};​


​20​

​//用来创建唯一的ID的计数器​


​21​

​addEvent.guid = 1;​


​22​

​function​​ ​​removeEvent(element, type, handler) {​


​23​

​//从哈希表中删除事件处理函数​


​24​

​if​​ ​​(element.events && element.events[type]) {​


​25​

​delete​​ ​​element.events[type][handler.$$guid];​


​26​

​}​


​27​

​};​


​28​

​function​​ ​​handleEvent(event) {​


​29​

​var​​ ​​returnValue = ​​​​true​​​​;​


​30​

​//抓获事件对象(IE使用全局事件对象)​


​31​

​event = event || fixEvent(window.event);​


​32​

​//取得事件处理函数的哈希表的引用​


​33​

​var​​ ​​handlers = ​​​​this​​​​.events[event.type];​


​34​

​//执行每一个处理函数​


​35​

​for​​ ​​(​​​​var​​ ​​i ​​​​in​​ ​​handlers) {​


​36​

​this​​​​.$$handleEvent = handlers[i];​


​37​

​if​​ ​​(​​​​this​​​​.$$handleEvent(event) === ​​​​false​​​​) {​


​38​

​returnValue = ​​​​false​​​​;​


​39​

​}​


​40​

​}​


​41​

​return​​ ​​returnValue;​


​42​

​};​


​43​

​//为IE的事件对象添加一些“缺失的”函数​


​44​

​function​​ ​​fixEvent(event) {​


​45​

​//添加标准的W3C方法​


​46​

​event.preventDefault = fixEvent.preventDefault;​


​47​

​event.stopPropagation = fixEvent.stopPropagation;​


​48​

​return​​ ​​event;​


​49​

​};​


​50​

​fixEvent.preventDefault = ​​​​function​​​​() {​


​51​

​this​​​​.returnValue = ​​​​false​​​​;​


​52​

​};​


​53​

​fixEvent.stopPropagation = ​​​​function​​​​() {​


​54​

​this​​​​.cancelBubble = ​​​​true​​​​;​


​55​

​};​


功能非常强悍,解决IE的this指向问题,event总是作为第一个参数传入,跨浏览器就更不在话下。

最后贡献一个HTML5工作组的版本:




​01​

​var​​ ​​addEvent=(​​​​function​​​​(){​


​02​

​if​​​​(document.addEventListener){​


​03​

​return​​ ​​function​​​​(el,type,fn){​


​04​

​if​​​​(el.length){​


​05​

​for​​​​(​​​​var​​ ​​i=0;i<el.length;i++){​


​06​

​addEvent(el[i],type,fn);​


​07​

​}​


​08​

​}​​​​else​​​​{​


​09​

​el.addEventListener(type,fn,​​​​false​​​​);​


​10​

​}​


​11​

​};​


​12​

​}​​​​else​​​​{​


​13​

​return​​ ​​function​​​​(el,type,fn){​


​14​

​if​​​​(el.length){​


​15​

​for​​​​(​​​​var​​ ​​i=0;i<el.length;i++){​


​16​

​addEvent(el[i],type,fn);​


​17​

​}​


​18​

​}​​​​else​​​​{​


​19​

​el.attachEvent(‘on‘+type,​​​​function​​​​(){​


​20​

​return​​ ​​fn.call(el,window.event);​


​21​

​});​


​22​

​}​


​23​

​};​


​24​

​}​


​25​

​})();​


可能细心的读者发现了IE的attachEvent和W3C标准的addEventListener绑定多个事件的执行顺序是不一样的