正值初夏,了解一下JavaScript事件管理

简介: 正值初夏,了解一下JavaScript事件管理

我正在参加「初夏创意投稿大赛」详情请看:初夏创意投稿大赛

炎炎夏日 ,今天你学习了吗?

当我们拥有一堆代码,且看不懂的时候,这个时候我们就该想该如何去重构该代码,此时我们就可以采用自定义事件管理的方式,能够更好的管理维护代码,这个时候就会发起疑问了,为什么要采用这种方式呢,个人认为自定义事件管理有以下优点:

  • 占用内存小,项目启动快,能够很好的提高性能
  • 减少事件注册,不会覆盖掉之前的相同事件

他的缺点也很明显,因为它不会覆盖掉之前相同的事件,就极有可能会出现事件混乱运行的情况,这里需要注意一下

如何实现自定义事件管理


自定义事件管理,实现的方法有很多,我这里讲俩种方案,思路都是基本一样,自定义事件管理是把所有事件放到一个地方统一管理,可以进行删除,添加,触发,存储事件的地方叫做事件池,事件池存放了所有触发元素和事件;

ES5实现方式


事件池:用于管理自定义事件

//事件池
/**
* 存储后的数据:key是事件管理名,val是一个数组,里面是事件
"mydom":['事件1','事件2']
**/
const handle={};

往事件池里面添加事件

/**
EventName 事件管理名
fn 需要添加的事件
 */
 function addEvent(EventName, fn) {
 // 判断事件名是否存在于事件池,如果不存在则创建一个空数组
   if (!(EventName in handle)) {
       handle[EventName] = [];
   };
  // 添加进去
  handle[EventName].push(fn);
 };

删除事件

/**
EventName 事件管理名
fn 需要删除的事件
 */
 function removeEvent(EventName, fn) {
   // 判断当前的事件管理名是否存在,不存在则退出
   if (!(EventName in handle)) {
                return;
            };
let i = handle[EventName].findIndex(val => {
    // 判断当前的元素是否存在,存在返回当前元素的索引值,不存在则返回-1
         return val == fn;
   });
 if (i == -1) {
     // 没有找到事件则退出
    return console.error('没有找到事件')
   };
// 使用数组方法删除下标为i的数组,操作的是原数组
    handle[EventName].splice(i, 1);
  };

触发事件

/**
EventName 事件管理名,用于事件名下管理的所有事件
 */
 function triggerEvent(EventName) {
    // 判断当前的事件管理名是否存在,不存在则退出
    if (!(EventName in handle)) {
        console.error(EventName, '事件名不存在');
        return;
    };
    // 存在则执行事件管理中的所有事件
    // for和foreach的区别:for可以退出可以跳过但是foreach不行;
    handle[EventName].forEach(elm => {
        // 执行
        elm();
    });
};

使用

//声明事件
 function fn1() {
     console.log('自定义事件1');
}
function fn2() {
   console.log('自定义事件2');
};
//  添加事件
addEvent('myevent', fn2);
addEvent('myevent', fn1);
//删除事件
removeEvent('myevent', fn1);
//执行事件
btn.addEventListener('click', () => {
  triggerEvent('myevent');
});

看到代码想必大家明白了个大概,下面贴出完整代码

// 事件
        function fn1() {
            console.log('自定义事件1');
        }
        function fn2() {
            console.log('自定义事件2');
        };
        // 事件池
        const handle = {};
        // 添加事件
        function addEvent(EventName, fn) {
            if (!(EventName in handle)) {
                handle[EventName] = [];
            };
            handle[EventName].push(fn);
        };
        // 执行函数
        function triggerEvent(EventName) {
            if (!(EventName in handle)) return;
            handle[EventName].forEach(elm => {
                elm();
            });
        };
        // 删除事件
        function removeEvent(EventName, fn) {
            if (!(EventName in handle)) return;
            let i = handle[EventName].findIndex(val => {
                return val == fn;
            });
            if (i == -1) return;
            handle[EventName].splice(i, 1);
        };
        //  添加 
        addEvent('myevent', fn2);
        addEvent('myevent', fn1);
        // 删除
        removeEvent('myevent', fn1);
        // 执行
        btn.addEventListener('click', () => {
            triggerEvent('myevent');
        });

ES6实现方式


现在es6已经基本全面普及,怎么可能我们每天都会用到的es6方案呢,强烈推荐es6方案,es6方案比es5看起来更具有结构化,看起来更为清晰这里直接贴代码,思路基本都一样的

// 类
        class MyEvent {
            constructor() {
                    // 事件池
                    this.halder = {}
                }
                /**
                 *添加自定义事件
                 * 自定义事件管理名
                 *   事件名
                 */
            addEvent(EventName, fn) {
                    // 判断当前的事件管理是不是为空
                    if (typeof this.halder[EventName] === 'undefined') {
                        this.halder[EventName] = [];
                    };  
                    // 把事件追加进去事件管理名
                    this.halder[EventName].push(fn);
                }
                /**
                 *删除自定义事件
                 * EventName 自定义事件管理名
                 *  fn  事件名
                 */
            removeEvent(EventName, fn) {
                    // 判断当前的事件管理是不是为空
                    if (!(EventName in this.halder)) return;
                    // 找到当前的事件在事件名中的下标并返回,没有返回-1
                    let i = this.halder[EventName].findIndex(v => {
                        return v == fn;
                    });
                    if (i === '-1')  return;
                    // 删除事件,对元素组进行操作的
                    this.halder[EventName].splice(i, 1);
                }
                /**
                 * 执行自定义事件
                 * EventName 自定义事件管理名
                 */
            tgigerEvent(EventName) {
                // 判断当前的事件管理是不是为空
                if (!(EventName in this.halder))return;
                this.halder[EventName].forEach(v => v());
            }
        };
        // 创建函数
        function fn1() {
            console.log('事件管理1');
        }
        function fn2() {
            console.log('事件管理2');
        }
        // 创建实例化对象
        let obj = new MyEvent();
        // 添加
        obj.addEvent('my', fn1);
        obj.addEvent('my', fn2);
        // 删除
        obj.removeEvent('my', fn2);
        // 执行
        btn.addEventListener('click', () => {
            obj.tgigerEvent('my');
        });


相关文章
|
3月前
|
JavaScript 前端开发
|
3月前
|
JavaScript 算法
|
3月前
|
JavaScript
|
22天前
|
JavaScript
事件触发、事件捕获与事件冒泡(js的问题)
事件触发、事件捕获与事件冒泡(js的问题)
12 0
|
3天前
|
JavaScript 前端开发
js开发:请解释事件冒泡和事件捕获。
JavaScript中的事件处理有冒泡和捕获两种方式。事件冒泡是从子元素向上级元素传递,而事件捕获则从外层元素向内层传递。`addEventListener`的第三个参数可设定事件模式,`false`或不设为冒泡,`true`为捕获。示例代码展示了如何设置。
19 2
|
24天前
|
JavaScript 前端开发 流计算
JS:oninput和onchange事件的区别
JS:oninput和onchange事件的区别
21 1
|
1月前
|
JavaScript 前端开发
js开发:请解释事件冒泡和事件捕获。
JavaScript中的事件处理有冒泡和捕获两种方式。事件冒泡是从子元素向上级元素依次触发事件,而事件捕获则从最外层元素向内层元素传递。`addEventListener`的第三个参数可设定事件模式,`false`或不设为冒泡,`true`为捕获。例如: ```javascript element.addEventListener('click', console.log, false); // 冒泡 element.addEventListener('click', console.log, true); // 捕获 ```
18 0
|
1月前
|
JavaScript 前端开发
JS页面加载事件
JS页面加载事件
|
1月前
|
JavaScript
|
1月前
|
JavaScript 前端开发
js阻止浏览器默认事件和防止事件传播事件
js阻止浏览器默认事件和防止事件传播事件
21 3