JavaScript进阶(五十二):自己实现一个事件队列

上篇博客我们已经知道了事件队列的本质,那么这里我们就来自己搞一个。

首先,它是一个 class:

JavaScript进阶(五十二):自己实现一个事件队列_第1张图片

然后 constructor 里面,别的不太需要,我就需要一个 pieps:

JavaScript进阶(五十二):自己实现一个事件队列_第2张图片

为什么是 pieps,带 s 的呢?因为我同一个管道,我是可以同时处理很多种事件的。

我希望的是,你可以给我好多种事件,我都可以认,这个是没问题的,所以我们这是个 pipes,带 s 的。

 

然后在我这,我会有两种人。

一种是,申明我需要监听某种事件。

而另一种人是说,我这发生了某个事件,它们都跟我打交道。

所以这时候,我需要 2 个方法。

 

一个是注册这个监听的,我就叫它 addListener:

JavaScript进阶(五十二):自己实现一个事件队列_第3张图片

当然顺便一说,如果用过 vue,$on 这个名字你可能会更加熟系一些:

JavaScript进阶(五十二):自己实现一个事件队列_第4张图片

这个先不管,名字叫啥都行,我们先用 addListener 这个。

然后我们 addListener 的时候,需要申明几件事,首先,你想监听对吧?

没问题,但你得告诉我,你要监听什么事件,所以我们需要一个 type:

JavaScript进阶(五十二):自己实现一个事件队列_第5张图片

以及接下来,我们除了 type 以外,还需要一个 function:

JavaScript进阶(五十二):自己实现一个事件队列_第6张图片

就是将来这个事件来了,我怎么告诉你,你得给我说呀。

 

那么接下来就非常简单了,因为我的 pipes 默认都是空的,就是一个 json。

所以我们可以这么来:

JavaScript进阶(五十二):自己实现一个事件队列_第7张图片

说白了就是,如果它本来这个 type 就存在,那我就直接用以前的。

如果没有,那我就初始化一个空数组。

为什么是数组?很简单,因为同一个事件可能有好多个人都在等,所以他们在一个数组里面。

 

然后接下来,我就在给它再 push 一个新人,又多一个要监听的:

JavaScript进阶(五十二):自己实现一个事件队列_第8张图片

就这么简单。

 

接下来我这还有一个,我叫它 dispatch:

JavaScript进阶(五十二):自己实现一个事件队列_第9张图片

这个 dispatch,就是我要触发一个事件了。

那么我得告诉它我要触发什么事件吧?所以在这还需要个 type:

JavaScript进阶(五十二):自己实现一个事件队列_第10张图片

以及,我们还有一些参数:

JavaScript进阶(五十二):自己实现一个事件队列_第11张图片

之所以这么写,原因很简单,你可以随便传参数,传 100 个都行。

 

然后接下来,我们就来看一看:

如果 this.pipes 里面的 type 是有的,换句话说,就是以前有人去注册过这个事件。

如果压根没人注册过,那我就什么都不管,就仍了:

JavaScript进阶(五十二):自己实现一个事件队列_第12张图片

那大家可能会奇怪,万一这个事件没人监听,它不应该存起来吗,等以后有人监听了在给?

其实一般是不会的,像是DOM事件,其实也是这样的。

比如我们 js 进阶五十用的例子:

假设按钮 2 这只是有 dispatch,但是就没有人监听这个事件。

JavaScript进阶(五十二):自己实现一个事件队列_第13张图片

那么这时候你可以看到,我点了就是白点。

也不会报错,也什么都不会发生,就是没人监听。

 

然后直到某一天,有人监听了。

比方说,我们加个 setTimeout:

JavaScript进阶(五十二):自己实现一个事件队列_第14张图片

那么你可以看到,在 console.log('定时器触发了') 出来之前,怎么点都是没反应的。

因为现在就没人盯着这个事件。

 

直到有一天,有人开始监听这个事件了,就是 console.log('定时器触发了') 出来之后。

然后这时候我再点,才有反应:

JavaScript进阶(五十二):自己实现一个事件队列_第15张图片

这很正常。

就是说,之前没人监听的那个时候,那个事件就是没的,消失的。

这很正常,所有的事件监听器都是这么工作的。

 

然后我们继续。

那如果有人监听这个事,别忘了我是个数组,不一定只是一个人,也可能是一堆人,那么这时候我就来 forEach 一下。

别忘了,我们这个数组里面放的都是函数,那么我要做的就非常的简单,我就执行这个函数,并且把 args 给它带进去:

JavaScript进阶(五十二):自己实现一个事件队列_第16张图片

那么到这为止,我们这个事件队列就已经定义完了。

代码绝对不复杂,但这个东西它胜在本身很巧妙。

 

接下来我们来试试。

比如现在,我们不想用 DOM 事件,就想触发一个我自己自定义的事件。

那么首先,我们先引入,并且实例化:

JavaScript进阶(五十二):自己实现一个事件队列_第17张图片

然后接下来的 btn1,我们还需要去监听吗?压根就不需要。

我们直接找 pipe 来 addListener:

JavaScript进阶(五十二):自己实现一个事件队列_第18张图片

并且我要获取到一个通知:

JavaScript进阶(五十二):自己实现一个事件队列_第19张图片

可以看到,比原来的写法还要精简很多。

 

以及接下来,我们在 btn2 里面想触发。

我们直接 dispatch,触发一个 aaa 就可以了:

JavaScript进阶(五十二):自己实现一个事件队列_第20张图片

然后我们来试试:

JavaScript进阶(五十二):自己实现一个事件队列_第21张图片

可以看到,是能触发了。

当然我们也可以传参,比如我现在传了一个 12,5:

JavaScript进阶(五十二):自己实现一个事件队列_第22张图片

那么我们也打印下,看看能不能出来:

JavaScript进阶(五十二):自己实现一个事件队列_第23张图片

可以看到,点 按钮2 的时候,也是能触发的,并且参数也能过去。

其实跟 DOM 所带的那套事件,是一模一样的,并且比它那个还要精简很多,用起来也方便很多。

 

然后我们现在想要来测试一个东西,因为我们一直都在鄙视 DOM,说它性能不行。

那么我们现在完全可以试试,看看它性能到底行不行。

 

我们先来看看传统的 DOM 事件。

比方说,我们做个 10W 次循环,在循环里面做的就是,不停的创建事件,派发事件:

JavaScript进阶(五十二):自己实现一个事件队列_第24张图片

我们取 3 次的平均值,这样更准确一些:

JavaScript进阶(五十二):自己实现一个事件队列_第25张图片

那么结果是: 

(381 + 369 + 383) / 3 = 377.66 ms

 

然后我们再用 pipe 试一次:

JavaScript进阶(五十二):自己实现一个事件队列_第26张图片

同样取 3 次平均值:

JavaScript进阶(五十二):自己实现一个事件队列_第27张图片

结果是: 

(12 + 9 + 10) / 3 = 10.33 ms

可以看到,基本是有 36 倍的性能差。

所以说,只要跟 DOM 沾边的东西,你会发现它性能都不咋地。

那么现在这个时候,我们就已经完成了事件队列的这个过程。

 

然后先肯定一点,我们个人其实不太倾向去使用 addListener 和 dispatch 这么长的名字,因为用起来不是很方便。

JavaScript进阶(五十二):自己实现一个事件队列_第28张图片

所以有很多人喜欢管它们叫做 on 和 emit:

JavaScript进阶(五十二):自己实现一个事件队列_第29张图片

相信大家首先肯定会想到 vue,其实不是的。

基本上来说,所有的这些事件队列库都叫这 2 个名字,并不是只有 vue 专用。

那么在这种情况下,我们用这 2 个名字,就更加的精简一些。

 

你可能感兴趣的:(JavaScript进阶,javascript)