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或者applythis指向target,并且考虑到事件状态的参数将window.event作为参数传进去。

1
2
3
4
5
6
//将第二种修改
return function (target, type, handler) {
target.attachEvent('on' + type, function () {
handler.call(target, window.event)
})
}

目录都去哪了...