DOM事件、事件委托

266 阅读3分钟

点击事件

关于点击事件,可以通过一下代码来进行解答。

<div class="no1">
   <div class="no2">
  	 <div class="no3">
            文字
  	</div>
   </div>
</div>

再给三个div添加事件监听“fnNo1、fnNo2、fnNo3”,就是谁被点击了就执行谁。

问题一:点击了谁

  • 点击文字,算不算点击“no1”? 答案:算!

  • 点击文字,算不算点击“no2”? 答案:算!

  • 点击文字,算不算点击“no3”? 答案:算!

通过以上代码可以得出,当我们点击子元素(no3)的时候,会将父元素和根元素同时点击一遍。

问题二:调用顺序

  • 点击文字,最先调用fnNo1、fnNo2、fnNo3中的哪一个函数? 答案:都可以,主要看浏览器是这么实现的。

解析:在之前IE5认为应该先调用子元素,因为子元素最近所以先调用子元素。但是跟它同一时期的网景浏览器跟IE唱反调,网景说应该先调用跟元素,因为跟元素最大,所以应该通知跟元素。

  • W3C标准

后来W3C在2002年,发布了关于事件调用顺序的标准,文档名为“DOM Level2 Events Specification”,规定浏览器应该同时支持两种调用顺序。

1.首先按照根元素=>父元素=>子元素的顺序看看有没有函数监听。

2.然后按照子元素=>父元素=>根元素的顺序看看有没有函数监听。

有函数监听就调用,并提供事件信息,没有就直接跳过。

术语

  • 从外向内找监听函数,叫事件捕获。

  • 从内向外找监听函数,叫事件冒泡。

DOM冒泡阶段和捕获阶段示意图

1.png

事件绑定API

addEventListener //绑定事件
IE5:  no2.attachEvent('onclick',fn) //默认冒泡
网景: no2.addEventListener('click',fn) //默认捕获
W3C:  no2.addEventListener('click',fn,bool)
  • 如果bool不传或者不传为falsy 就让fn走冒泡,即当浏览器在冒泡阶段发现no2有fn监听函数,就会调用fn,并提供事件信息。

  • 如果boll为true 就让fn走捕获,即当浏览器在捕获阶段发现no2有fn监听函数,就会调用fn,并提供事件信息。

总结!

  • 两个疑问
  1. 子元素被点击,算不算点击根元函数?

算!因为这部分其中任意一个div被点击了,全都被点击了。

  1. 先调用根函数还是先调用子函数? 不确定!如果是在IE的浏览器就是先调用子函数,如果是在Firefox浏览器就是先调用父元函数。

捕获与冒泡

捕获:先调用父的监听函数

冒泡:先调用子的监听函数

DOM事件模型

先捕获(先父元素=>子元素)再冒泡(再子元素=>父元素)

事件委托

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。

事件委托可以大量节省内存占用,减少事件注册。

怎么阻止默认动作:

取消某个特定元素的wheel 和touchstart的默认动作

阻止冒泡:

e.stopPropagation()可中断冒泡 但是scroll 不支持取消冒泡