油候脚本重构addEventListener()、removeEventListener()、getEventListener()等函数

说明:

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参数

 

 

【出处】:https://blog.csdn.net/handsomeAndHero/article/details/126716319

=======================================================================================

posted on   jack_Meng  阅读(155)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
历史上的今天:
2022-01-10 《三字经》全文带拼音
2019-01-10 使用dynamic和MEF实现轻量级的AOP组件 ---- 系列文章
2019-01-10 【.Net平台下插件开发】-MEF与MAF初步调研
2019-01-10 使用Managed Extensibility Framework方便的扩展应用程序
2019-01-10 SVN提交强制输入日志信息
2019-01-10 AspNetCore+Swagger 生成Model描述
2019-01-10 AspNet Core Api Restful +Swagger 发布IIS

导航

< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示

喜欢请打赏

扫描二维码打赏

支付宝打赏

主题色彩