DOM事件与事件委托

Rinsann 2021年08月29日 549次浏览

DOM事件与事件委托

点击事件

  1. W3C规定了浏览器应该同时支持两种调用顺序
  2. 首先按照爷爷=>爸爸=>儿子 顺序看看有没有函数监听
  3. 然后按照儿子=>爸爸=>爷爷 顺序看看有没有函数监听
  4. 有监听函数就调用,并提供事件信息,没有就跳过

术语

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

疑问:那岂不是都调用了两次?不是!

开发者自己选择把元素放在捕获阶段还是放在冒泡阶段

示意图

image20210904181751160.png

addEventListener

事件绑定API

  • IE5*:bab.attachEvent(‘onclick’,fn) //冒泡
  • 网景:bab.addEventListener(‘click’,fn) //捕获
  • W3C:bab.addEventListener(‘click’,fn,bool)

如果bool不传或为falsy

  • 就让fn冒泡,即当浏览器在冒泡阶段发现bab有fn监听函数,就会调用fn,并提供事件信息

如果bool为true

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

可以选择把fn放在哪边

image20210904210256542.png

代码图解

image20210904211559391.png

两个疑问

  • 子元素被点击了,算不算点击父元素?
  • 那么先调用父元素的函数还是先调用子元素的函数?

捕获与冒泡

  • 捕获说先调用父元素的监听函数
  • 冒泡说先调用子元素的监听函数

W3C事件模型

  • 先捕获(先父=>子) 在冒泡 (再子=>父)
  • 注意e对象被传给所有监听函数
  • 事件结束后,e对象就不存在了

target V.S. currentTarget

区别

  • e.target-用户操作的元素
  • e.currentTarget-程序员监听的元素
  • this是e.currentTarget,但是不推荐使用它

举例

  • div > span{文字},用户点击文字
  • e.target 就是 span
  • e.currentTarget 就是 div

一个特例

背景

  • 只有一个div被监听(不考虑父子同时被监听)
  • fn分别在捕获阶段和冒泡阶段监听click事件
  • 用户点击的元素就是开发者监听的

代码

  • div.addEventLisenter(‘click’,f1)
  • div.addEventLisenter(‘click’,f2,true)
  • 问,f1先执行还是f2先执行,如果把两行调换位置后,那个先执行?
  • 正确答案:谁先监听谁先执行,这是一个特例。

e.stopPropagation():取消冒泡

e.stopPropagation()可打断冒泡,浏览器不再向上走

  • 一般用于封装某些独立组件
  • 注意:捕获不可以取消但是冒泡可以(有些事件也不能够取消冒泡)

事件委托

我委托一个元素帮我监听我本该监听的东西,比如onclick
场景1:

  • 要给100个按钮添加点击事件,咋办?
  • 答:监听这个100个按钮的祖先,等冒泡的时候判断target是不是这100个按钮中的一个

场景2:

  • 你要监听目前不存在的元素的点击事件?
  • 答:监听祖先,等点击的时候看看是不是监听的元素即可。
  • 优点:省监听数(内存),可以动态监听元素

封装一个事件委托

只要实行一个函数就可以实现事件委托

要求:

  • 写出这样一个函数on('click','#testDiv','li',fn)
  • 当用户点击#testDiv里面的li元素时,调用fn函数

要求用到事件委托

  • 答案1:判断target是否匹配'li'
  • 答案2:target/target的爸爸/target的爷爷