说明:
addEventListener() 方法用于向指定元素添加监听事件。且同一元素目标可重复添加,不会覆盖之前相同事件,配合 removeEventListener() 方法来移除事件。
我们知道原生js的removeEventListener() 方法是无法移除匿名函数事件,因为某些原因又不想添加第三方的js库来实现,我们可以自己重构addEventListener()、removeEventListener()等方法来实现移除匿名函数的事件,重构代码如下:
(function () {
'use strict';
// 在覆盖原始方法之前保存它们
Element.prototype._addEventListener = Element.prototype.addEventListener;
Element.prototype._removeEventListener = Element.prototype.removeEventListener;
/**
* 添加事件监听
* @param {[type]} type [事件类型,如:click]
* @param {[type]} listener [执行函数]
* @param {Boolean} useCapture [触发类型,true=事件在捕获阶段执行,false=冒泡阶段]
* @param {string} notes 可空,备记文本,用于备记事件的说明,方便用于区分相同的事件、函数属于什么功能
*/
Element.prototype.addEventListener = function (type, listener, useCapture = false, notes) {
// 申明事件监听器
this._addEventListener(type, listener, useCapture);
if (!this.eventListenerList) this.eventListenerList = {};
if (!this.eventListenerList[type]) this.eventListenerList[type] = [];
// 将侦听器添加到事件跟踪列表
this.eventListenerList[type].push({ type, listener, useCapture, notes });
};
/**
* 移除事件监听器
* @param {[type]} type [事件类型,如:click]
* @param {[type]} listener [执行函数]
* @param {Boolean} useCapture [触发类型]
* @return {[type]} [description]
*/
Element.prototype.removeEventListener = function (type, listener, useCapture = false) {
// 移除监听器
this._removeEventListener(type, listener, useCapture);
if (!this.eventListenerList) this.eventListenerList = {};
if (!this.eventListenerList[type]) this.eventListenerList[type] = [];
// 在列表中查找事件,如果侦听器注册了两次,则有捕获和无捕获,分别移除每一个。
for (let i = 0; i < this.eventListenerList[type].length; i++) {
if (this.eventListenerList[type][i].listener === listener && this.eventListenerList[type][i].useCapture === useCapture) {
this.eventListenerList[type].splice(i, 1);
break;
}
}
// 如果不再保留已删除事件类型的事件,则删除该组
if (this.eventListenerList[type].length == 0) delete this.eventListenerList[type];
};
/**
* [获取事件监听]
* @param {[type]} type [事件类型]
* @return {[type]} [返回目标所有事件]
*/
Element.prototype.getEventListeners = function (type) {
if (!this.eventListenerList) this.eventListenerList = {};
// 返回所需的侦听器类型或所有侦听器
if (type === undefined) return this.eventListenerList;
return this.eventListenerList[type];
};
})();
这样我们就重构好了事件监听器,并额外添加了getEventListeners()方法,就可以取出所有的监听事件,从已监听的事件列表中找出对应的事件使用removeEventListener进行删除即可,即使是匿名事件也可以,原生的移除方法不支持匿名的原因是我们的无法提供的添加时的匿名事件,尽管我们提供的匿名函数名称一样但是内存里的指向是不同的函数地址,现在我们就完美的解决了。
备记方法移除事件例子:
// 获取目标元素的所有监听事件,这里以click事件为例
let eventTarget = elem.getEventListeners().click
// 如果事件对象不为未定义,就表示已经添加过click事件
if (eventTarget != undefined) {
// 倒叙循环 获取事件对象里有指定备记的事件
for (let i = eventTarget.length - 1; i >= 0; i--) {
if (eventTarget[i].notes === notes) {
// 移除事件 使用事件列表里记录的事件函数
elem.removeEventListener('click', eventTarget[i].listener)
}
}
}
直接移除事件例子:
// 获取目标元素的所有监听事件,这里以click事件为例
let eventTarget = elem.getEventListeners().click
// 如果事件对象不为未定义,就表示已经添加过click事件
if (eventTarget != undefined) {
// 删除第一个事件(无论是否匿名事件)
elem.removeEventListener('click', eventTarget[0].listener)
}
写法于原生js的事件监听写法一致,其中addEventListener()方法比原生方法多了一个notes参数