当前位置: IT培训 > HTML5培训 > 前端开发 > JS > 简单几分钟让你轻松理解javascript事件机制
简单几分钟让你轻松理解javascript事件机制 时间:2017-08-08     来源:javascript开发小赢家

先让我们看看一般情况我们要给一个html元素添加点击事件我们会怎么做。

方法一:

5分钟轻松理解JavaScript 事件机制

方法二:

5分钟轻松理解JavaScript 事件机制

这可能是我们常用的两种方式,当然JQuery还提供bind,on等函数来绑定事件。

而今天我们要来看的是更底层的,用原始JavaScript提供的函数来完成事件绑定。虽然在实际工作中我们很少会直接使用这些函数,但是通过对这些函数的了解,可以更深刻的理解JavaScript的事件机制。

EventTarget接口

任何部署了EventTarget接口的对象都可以拥有自己的事件。任何元素节点 ,document节点 及window对象都部署了这个接口。也就意味着我们可以给任何html 元素节点添加事件。除了标准的click事件等还可以绑定自定义事件。

addEventListener 绑定事件的监听函数

removeEventListener 移除事件的监听函数

dispatchEvent 触发事件

addEventListener方法用于在当前节点或对象上,定义一个特定事件的监听函数。
<div id='foo'></div>

我们给这个元素添加点击事件可以

5分钟轻松理解JavaScript 事件机制

通过上面的代码div 就可以捕捉click事件了。当点击div时就会触发hello函数打印字符串。

这里有个问题:

5分钟轻松理解JavaScript 事件机制

点击一次后会打印1个Hello world 还是2个?

如果再换成这样呢?

5分钟轻松理解JavaScript 事件机制

上面两个问题大家可以自己动手试试。看看addEventListener的添加事件的特点。

接下来我们看看如果需要传参数给触发函数怎么办?

现在我们的需求变成点击一个元素,然后传一个名字到函数中打印hello xxx。

5分钟轻松理解JavaScript 事件机制

通过匿名函数的封装可以达到传递参数的目的。

说完点击事件,让我们来看看如何自定义事件。现在我想给元素添加一个vic事件,事件触发后打印hello vic。

5分钟轻松理解JavaScript 事件机制

问题是我们要怎么触发vic事件呢?答案是dispatchEvent函数

5分钟轻松理解JavaScript 事件机制

定义一个名为vic 的事件对象,然后通过dispatchEvent传递这个事件。

removeEventListener函数用法与addEventListener 函数一样,只是它是用来删除对某一个事件的响应,就不多做介绍了。

接下来是这篇文章的重头戏,很多朋友就是因为不理解事件的传播,导致一些奇怪的现象发生。

让我们来看看事件到底是如何进行传播的?

第一阶段:从window传递到目标节点称为捕获阶段

第二阶段:在目标节点触发称为目标阶段

第三阶段:从目标节点传回window对象,称为冒泡阶段

让我们来看个例子:

5分钟轻松理解JavaScript 事件机制

输出结果是

5分钟轻松理解JavaScript 事件机制

当然你可以把上面添加事件的顺序随意更改,打印结果还是不会变的。

可以看出来当我们点击div时,click事件先到window对象上,触发了window对象的click事件(捕获阶段),然后事件到了document对象上触发了click事件(捕获阶段),接着又到了body对象上触发了click事件(捕获阶段),接着来到div对象上触发了click事件(我理解为捕获结束的目标阶段),然后事件准备冒泡,先是触发了div对象的click事件(我理解为冒泡阶段的目标阶段),然后来到body对象上触发了click事件(冒泡阶段),接着到了document, 后到window对象。

可以看到仅仅是在body下定义了一个div元素,我们就可以有8个地方来处理在div触发的click事件。当然我们往往不会这么做,一般情况下只会在div上添加click事件触发函数。

让我们来看后一个问题:我希望body能响应click事件,打印hello body。 同时我希望div能响应click事件,打印hello div。但是我不希望点击div的时候打印出hello body。

5分钟轻松理解JavaScript 事件机制

这里为body设置样式是为了让body比div范围更大。当我们点击body而不是div的时候,可以看到只打印hello body.但是当我们点击div的时候看到先打印了hello div,再打印了hello body。对应上面的事件阶段分析,我们很容易得出是怎么回事。因为在冒泡阶段click事件到达div后继续冒泡到了body,使body的click的事件触发了。有的朋友可能会问,为什么点body不会触发div的click事件呢?那是因为用户点击网页的时候,浏览器总是假定click事件的目标节点,就是点击位置的嵌套深的那个节点。当我们点击body区域但是不属于div的区域时,目标节点为body,所以当body处理click事件后就往上冒泡了。但是当我们点击div区域时,目标节点是div,而div的父节点为body,所以冒泡的时候会经过body。

那么有什么办法阻止冒泡吗?答案是stopPropagation。英语好的朋友一看这个函数名就知道它是干嘛用的了。那让我们加上看看效果。

5分钟轻松理解JavaScript 事件机制

stopPropagation函数是event对象上的一个方法。这样就达到了我们的目的,当点击div的时候,事件就不再继续往上冒泡了。所以点击div的时候body就不会触发click事件了。

X