DOM事件模型
一个事件发生之后,会在子元素个父元素之间进行传播,这种传播又分为三个阶段:
- 事件捕获:从外向内找监听函数——由微软公司提出
- 在目标节点触发事件
- 事件冒泡:从内向外找监听函数——由网景公司提出
W3C标准:首先捕获,再冒泡。
捕获
一个事件在被触发之时,浏览器会自动从用户操作标签外的最上级标签中逐渐向里面检查是否有相同的事件,如果有则触发,如果没有就继续向下检查,一直到用户操作的标签。这个过程就是捕获。
冒泡
此时浏览器会继续由用户操作标签向上级标签检查,如果发现有相同的事件测触发,如果没有就继续向上级检查指导最上级为止,这过程就是冒泡。
举一个点击事件的简单的例子:
<div class="grandfather">
<div class="father">
<div class="son"></div>
文字
</div>
</div>
捕获:.grandfather>.father>.son
冒泡:.son>.father>.granfather
给这三个div分别添加fnYe/fnBa/fnEr
问题1:请问点击文字,到底是点击了谁? 算不算点击了son?fanter?grandfather? 答:都算。 问题2:那么调用顺序又是什么? 答:都可以。
W3C使用addEventListener事件绑定API,判断触发事件是在捕获阶段还是冒泡阶段。
W3C:baba.addEventListener('click',fn,bool)
- 若bool不填或者为falsy值:那就让fn走冒泡阶段,就是说当浏览器在冒泡阶段发现baba有fn的监听函数,就调用fn,并提供事件信息。
- 若bool为true,则让fn走捕获。
target和currentTarget的区别
- e.target是用户操作的元素
- e.currentTarget是程序员监听的元素 举例:
<div>
<span>
文字
</span>
</div>
用户点击文字,e.target就是span,e.currentTarget就是div。
还有一个特例:只有一个div被监听(不考虑父子同时被监听),fn分别在捕获阶段和冒泡阶段监听click事件。用户点击的元素就是开发者监听的元素。
在这种情况下,div.addEventLisenter('click',f1)和div.addEventLisenter('click',f2,true)。f1和f2谁先执行?
答:谁先监听谁先执行。
取消冒泡
捕获不可以取消,但是冒泡可以取消。
使用e.stopPropagation()可以中断冒泡,浏览器不再向上走了。通俗的说:有人打我,我自己解决,不要告诉我老子。