JS中注册事件的兼容性封装
在JS中,提供了三种注册事件的方式:
1.对象.事件类型 = function(){};
2.对象.addEventListener(事件类型,事件处理函数,useCapture); //useCapture默认为false
3.对象.attachEvent(事件类型,事件处理函数);
但是上面的三种注册事件的方式都存在瑕疵:第一种对于同一个对象绑定相同的事件类型,后者会覆盖前者,而后两种则存在兼容性问题。


考虑到以上存在的问题以及要使用时代码的复用性较差,所以在这里可以考虑将其封装到一个函数中,每次使用的时候调用一下即可。
1 2 3 4 5 6 7 8 9
| function createEvent (target, type, handler) { if (target.addEventListener) { target.addEventListener(type, handler) } else if (target.attachEvent) { target.attachEvent('on' + type, handler) } else { target['on' + type] = handler } }
|
上面只是一个简单的封装,虽然看上去可以使用了,但是它还存在着一定的问题。就是每注册一次事件,在调用函数时都要进行判断一次,那么在数据多时会影响代码的性能。所以在这里可以采用更好的一种方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function createEvent () { if (window.addEventListener) { return function (target, type, handler) { target.addEventListener(type, handler) } } else if (window.attachEvent) { return function (targeet, type, handler) { target.attachEvent('on' + type, handler) } } else { return function (target, type, handler) { target['on' + type] = handler } } }
|
这个代码虽然看起来只是第一次的简单变形,但是却只需要在创建的时候判断一次,在使用的时候不需要判断了。
如果说以为上面的代码就可以放心使用,那就大错特错了。在attachEvent
这个注册事件的方式中,回调函数的this
指向的是window
,而其他两种都指向的是target
,所以在这里可以使用call
或者apply
让this
指向target
,并且考虑到事件状态的参数将window.event
作为参数传进去。
1 2 3 4 5 6
| return function (target, type, handler) { target.attachEvent('on' + type, function () { handler.call(target, window.event) }) }
|