DMO 事件与事件委托

一个点击事件

代码

<div class = 爷爷>
    <div class = 爸爸>
        <div class = 儿子>
            文字
        </div>
    </div>
</div>
复制代码

.爷爷>.爸爸>.儿子,给三个div分别添加事件监听 fnYe / fnBa / fnEr

问题1:点击了谁

点击文字,算不算点击儿子?

点击文字,算不算点击爸爸?

点击文字,算不算点击爷爷?

答案:都算

问题2:调用顺序

点击文字,最先调用 fnYe / fnBa / fnEr中的哪一个函数?

答案:都行

由来

IE5和网景

IE5认为先调fnEr,网景认为先调fnYe

2002年,W3C发布标准,文档名为 DOM Level 2 Events Specification,规定浏览器应该同时支持两种调用顺序。

首先爷爷=>爸爸=>儿子顺序看有没有函数监听

然后儿子=>爸爸=>爷爷顺序看有没有函数监听

有函数监听就调用,并提供时间信息,没有就跳过

术语

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

从内向外找监听函数,叫时间冒泡

并不是说 fnYe / fnBa / fnEr都要调用两次,开发者自行选择把f fnYe / fnBa / fnEr放在捕获阶段或冒泡阶段

示意图

image-20210505001231115.png

addEventListener

绑定事件API

IE5*: baba.attachEvent('onclick',fn) //冒泡
网景: baba.addEventListener('click',fn) //捕获
W3C: baba.addEventListener('click',fn,bool)
复制代码

如果bool不传或为falsy

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

如果bool为true

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

image-20210505173341969.png

代码演示

代码示例

冒泡演示

40.2.1.gif

捕获演示

40.2.2.gif

image-20210505005209112.png

注意e对象被传给所有监听函数,事件结束后,e对象就不存在了。

target V.S. currentTarget

区别

e.target用户操作的元素

e.currentTarget程序员监听的元素

thise.currentTarget

举例

div>span{文字},用户点击文字

e.target就是span

e.currentTarget就是div

一个特例

背景

只有一个div被监听(不考虑父子同时被监听)

fn分别在捕获阶段和冒泡阶段监听click事件

用户点击的元素就是开发者监听的

代码

div.addEventLisenter('click',f1)
div.addEventLisenter('click',f2,true)
复制代码

请问,f1先执行还是f2先执行?

答案:f1先执行,如果两行调换位置,f2先执行。

取消冒泡

捕获不可取消,但是冒泡可以取消

div.stoppropatation()
复制代码

可中断冒泡,浏览器不再向上走,一般用于封装某些独立的组件。

不可阻止默认动作

有些事件不能阻止默认动作

MDN搜索scroll event,能看到Bubbles(该事件是否冒泡,所有冒泡都可取消)和 Cancelable(开发者是否可以阻止默认事件),Cancelable与冒泡无关。

最好是看英文版,中文版内容不全。

image-20210505012907216.png

如何阻止滚动

scroll事件不可阻止默认动作

阻止scroll默认动作没用,因为先有滚动才有滚动事件

要阻止滚动,可以组织wheel和touchstart的默认动作

注意需要找准滚动条所在的元素,可用CSS让滚动条 width: 0

代码示例

CSS也行

使用overflow:hidden可直接取消滚动条

但此时JS依然可以修改scrollTop

自定义事件

浏览器自带事件

一共100多种事件,点击查看MDN

自定义事件

开发者可以在自带事件之外,自定义一个事件

点击查看示例

事件委托

场景一

代码

给100个按钮添加点击事件

监听这100个按钮的祖先,等冒泡的时候判断target是不是这100个按钮中的一个。

场景二

代码

监听目前不存在的元素的点击事件

监听祖先,等点击的时候看看是不是想要监听的元素即可。

优点

省监听数(内存)

可以监听动态元素

封装事件委托

要求

写出这样一个函数on('click','#testDiv','li',fn),当用户点击#testDiv里的li元素时,调用fn函数,要求用到事件委托。

代码

答案一:封装事件委托代码

答案二:递归判断 target / target的爸爸 / target的爷爷

整合进jQuery

可以尝试实现$('#xxx').on('click','li',fn)

JS支持事件吗

支持,也不支持。

本节课讲的DOM事件不属于JS的功能,术语浏览器提供的DOM功能(DOM和JS是平行关系)

JS只是调用了DOM提供的addEventListener而已

如何让JS支持事件?请手写一个事件系统。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享