ie7、ie8兼容addEventListener和removeEventListener,解决this指向和detachEvent解除绑定事件问题


  • 在浏览器中,dom监听事件使用addEventListener(removeEventListener);
    在ie7、ie8中,监听事件使用attachEvent(detachEvent)。
if(document.addEventListener){
    element.addEventListener(type, fun, useCapture);
}else{
    element.addEventListener("on" + type, fun);
}
  • addEventListener绑定的监听事件,事件内this指向element。但是attachEvent绑定的监听事件,事件内this指向window,使用call或者apply可以解决该问题,修改this指向element,event作为参数传递。
var addListener = (function(){
    if(document.addEventListener){
        return function(element, type, fun, useCapture){
            element.addEventListener(type, fun, useCapture ? useCapture : false);
        };    
    }else{
        return function(element, type, fun){
            element.attachEvent("on" + type, function(event){
                fun.call(element, event);
            });
        };
    }
})();

但是这样也有个问题,就是detachEvent无法解除监听,因为传递的事件已经改变了。

  • 通过function.prototype将修改后的函数和已经绑定该事件的dom储存起来,可以使detachEvent时能获取到解除监听的函数,并且避免dom多次绑定重复事件。
/**
 * addEventlistener兼容函数
 * ie9以上正常使用addEventlistener函数
 * ie7、ie8用传递的function的function.prototype._bindFun储存经过处理的事件和对应的节点
 * function.prototype._bindFun[index].type:绑定的事件类型
 * function.prototype._bindFun[index].element:绑定的节点
 * function.prototype._bindFun[index].Function:处理的事件
 */

/*** addEventlistener ***/
const addListener = (()=>{
    if(document.addEventListener){
        /* ie9以上正常使用addEventListener */
        return function(element, type, fun, useCapture){
            element.addEventListener(type, fun, useCapture ? useCapture : false);
        };
    }else{
        /* ie7、ie8使用attachEvent */
        return function(element, type, fun){
            if(!fun.prototype._bindFun){
                fun.prototype._bindFun = [];
            }
            // 判断当前的element是否已经绑定过该事件
            let s = true;
            for(const i in fun.prototype._bindFun){
                if(fun.prototype._bindFun[i].type === type && fun.prototype._bindFun[i].element === element){
                    s = false;
                    break;
                }
            }
            // 没有绑定事件
            if(s === true){
                const f = {
                    type: type,
                    element: element,
                    Function: function(event){
                        fun.call(element, event);
                    }
                };
                fun.prototype._bindFun.push(f);
                element.attachEvent(`on${type}`, f.Function);
            }
        };
    }
})();

/*** removeEventlistener ***/
const removeListener = (()=>{
    if(document.addEventListener){
        /* ie9以上正常使用removeEventListener */
        return function(element, type, fun){
            element.removeEventListener(type, fun);
        };
    }else{
        /* ie7、ie8使用detachEvent */
        return function(element, type, fun){
            for(const i in fun.prototype._bindFun){
                if(fun.prototype._bindFun[i].type === type && fun.prototype._bindFun[i].element === element){
                    element.detachEvent(`on${type}`, fun.prototype._bindFun[i].Function);
                    fun.prototype._bindFun.splice(i, 1);
                    break;
                }
            }
        };
    }
})();

你可能感兴趣的:(ie7、ie8兼容addEventListener和removeEventListener,解决this指向和detachEvent解除绑定事件问题)