移除元素所有事件监听_DOM 事件模型或 DOM 事件机制

DOM 事件模型

DOM 的事件操作(监听和触发),都定义在EventTarget接口。所有节点对象都部署了这个接口,其他一些需要事件通信的浏览器内置对象(比如,XMLHttpRequest、AudioNode、AudioContext)也部署了这个接口。

该接口主要提供三个实例方法。

  • addEventListener:绑定事件的监听函数
  • removeEventListener:移除事件的监听函数
  • dispatchEvent:触发事件

事件模型

一个事件发生后,会在子元素及父元素之间进行传播(propagation),这种传播分为三个阶段。

(这种三阶段的传播模型,使得同一个事件会在多个节点上触发。)

    1. 由外向内找监听函数就是事件捕获
    2. 在目标节点触发事件
    3. 由内而外找监听函数就是事件冒泡

通俗一点来说就是一个事件被触发时,浏览器会自动从用户操作标签外的最上级标签逐渐向里检查是否有相同事件,如果有则触发,如果没有则继续向下检查知道用户操作的标签,这过程称为捕获,此时浏览器会继续由用户操作标签继续向是上级标签检查,如果有相同事件则触发,如果没有则继续向上检查直到最上级元素为止,此过程称为冒泡。(有监听函数就执行,并提供事件信息,没有就跳过)

事件传播的最上层对象是window,上例的事件传播顺序,在捕获阶段依次为window、document、html、body、父节点、目标节点,在冒泡阶段依次为目标节点、父节点、body、html、document、window。

DOM事件传播的三个阶段:捕获阶段,目标阶段,冒泡阶段

点击事件

代码:

<div class="grandfather"><div class="father"><div class="son"></div>word</div>
</div>

即.grandfather>.father>.son

给三个div分别添加事件的监听fnYe/fnBa/fnEr

提问1:点击了谁?

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

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

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

答案:都算

提问2:调用循序

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

答案:都行

IE5认为先调用fnEr,网景认为先调用fnYe,最后遇到了W3C

2002年,w3c发布标准
文档名为DOM Level 2 Events Specification
规定浏览器应该同时支持两种调用顺序
首先按照grandfather->father->son
然后按照son->father->grandfather

术语:

从外向内找监听函数,叫做事件捕捉
从内向外找监听函数,叫做事件冒泡
那岂不是fnYe/fnBa/fnEr都调用两次,非也!
开发者可以自己决定把fnYe放在捕捉阶段还是放在冒泡阶段

5f4c06474c3e36a92c2f2c78556b3f64.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,并且提供事件信息。

c2116c00ae986bafbd441af619a3749e.png

代码演示:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>JS Bin</title>
</head>
<body>
<div class="level1 x"><div class="level2 x"><div class="level3 x"><div class="level4 x"><div class="level5 x"><div class="level6 x"><div class="level7 x"></div></div></div></div></div></div>
</div></body>
</html>

CSS:

* {box-sizing: border-box;
}
div[class^=level] {border: 1px solid;border-radius: 50%;display: inline-flex;
}
.level1 {padding: 10px;background: purple;
}
.level2 {padding: 10px;background: blue;
}
.level3 {padding: 10px;background: cyan;
}
.level4 {padding: 10px;background: green;
}
.level5 {padding: 10px;background: yellow;
}
.level6 {padding: 10px;background: orange;
}
.level7 {width: 50px;height: 50px;border: 1px solid;background: red;border-radius: 50%;
}
.x{background: transparent;//把元素的变为透明
}

Javascript代码:

const level1 = document.querySelector('.level1')
const level2 = document.querySelector('.level2')
const level3 = document.querySelector('.level3')
const level4 = document.querySelector('.level4')
const level5 = document.querySelector('.level5')
const level6 = document.querySelector('.level6')
const level7 = document.querySelector('.level7')let n = 1level1.addEventListener('click', (e)=>{const t = e.currentTarget//e只有在点击得一瞬间才会出现,所以要用t来记录一下。setTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1//因为如果每个时间都为1000那么就相当于在8点同时设置很多的闹钟,。知识
})
level2.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})
level3.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})
level4.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})
level5.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})
level6.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})
level7.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})

简化:

const level1 = document.querySelector('.level1')
const level2 = document.querySelector('.level2')
const level3 = document.querySelector('.level3')
const level4 = document.querySelector('.level4')
const level5 = document.querySelector('.level5')
const level6 = document.querySelector('.level6')
const level7 = document.querySelector('.level7')let n = 1const fm = (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
}const fa = (e)=>{const t =e.currentTargetsetTimeout(()=>{t.classList.add('x')},n*1000)n+=1}level1.addEventListener('click',fm,true)
level1.addEventListener('click',fa)
level2.addEventListener('click',fm,true)
level2.addEventListener('click',fa)
level3.addEventListener('click',fm,true)
level3.addEventListener('click',fa)
level4.addEventListener('click',fm,true)
level4.addEventListener('click',fa)
level5.addEventListener('click',fm,true)
level5.addEventListener('click',fa)
level6.addEventListener('click',fm,true)
level6.addEventListener('click',fa)
level7.addEventListener('click',fm,true)
level7.addEventListener('click',fa)

知识复习:

classList:

定义和用法

classList 属性返回元素的类名,作为 DOMTokenList 对象。

该属性用于在元素中添加,移除及切换 CSS 类。

classList 属性是只读的,但你可以使用 add() 和 remove() 方法修改它。

HTML DOM classList 属性​www.runoob.com

currentTarget 事件属性

定义和用法

currentTarget 事件属性返回其监听器触发事件的节点,即当前处理该事件的元素、文档或窗口。
在捕获和起泡阶段,该属性是非常有用的,因为在这两个节点,它不同于 target 属性。

currentTarget ʼþÊôÐÔ​www.w3school.com.cn

总结:

两个疑问:

儿子被点击,算不算点击老子?

那么先调用老子得函数还是先调用儿子的函数?

捕获冒泡

捕获说先调用爸爸的监听函数

冒泡说先调用儿子的监听函数

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.addEventListenter('click',f1)

div.addEventListenter('click',f2,true)

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

如果把两个调换位置?

总结:谁先监听谁先执行。

level7.addEventListener('click',()=>{console.log(2)
},true)//捕获
level7.addEventListener('click',()=>{console.log(1)
})//冒泡

e.stopPropagation():取消冒泡

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

一般用于封装某些独立组件

注意:捕获不可以取消但是冒泡可以

不可以取消冒泡

有些事件不可以取消冒泡

可以查阅MDN英文版冒泡

比如scroll:

a3f78b9f7ecaf71eeb642ddbc658611b.png

Bubbles:冒泡

Cancelable:是否取消冒泡

如何禁用滚动

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

JS Bin​js.jirengu.com
458783ef3f4c9d676cfebe3ab8409077.png

浏览器自带事件

来自MDN:

事件参考​developer.mozilla.org
04a10667cec1221014320944799dba8f.png

自定义事件:代码

JS Bin​js.jirengu.com
458783ef3f4c9d676cfebe3ab8409077.png

5a6336f11d64a8a22e2a2916176537a2.png

事件委托:

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

场景1:

要给100个按钮添加点击事件,咋办?

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

代码:

JS Bin​js.jirengu.com
458783ef3f4c9d676cfebe3ab8409077.png

场景2:

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

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

优点:省监听数(内存),可以动态监听元素

代码:

JS Bin​js.jirengu.com
458783ef3f4c9d676cfebe3ab8409077.png

封装一个事件委托

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

要求:

写出这样一个函数on('click','#testDiv','li',fn)

当用户点击#testDiv里面的li元素时,调用fn函数

要求用到事件委托

答案1:判断target是否匹配'li'

答案2:target/target的爸爸/target的爷爷

代码:

JS Bin​js.jirengu.com
458783ef3f4c9d676cfebe3ab8409077.png

错的但是面试可以用:

答:给一个元素加一个监听,看当前的target是否满足监听函数(函数2)中函数2的条件如果满足调用,不满足放过。但是是错的!

代码:

setTimeout(()=>{const button = document.createElement('button')const span = document.createElement('span')span.textContent='click 1'button.appendChild(span)div1.appendChild(button)
},1000)on('click','#div1','button',()=>{//'#div'是选择器不是元素console.log('button 被点击啦')
})
function on(eventType,element,selector,fn){if(!(element instanceof Element)){element = document.querySelector(element)}element.addEventListener(eventType,(e)=>{const t= e.target//被点击的元素是span不是button啦if(t.matches(selector)){//matches用来判断一个元素是否匹配一个选择器,selector是不是一个选择器
span不匹配buttonfn(e)}
})
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/541565.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ISCC2014-reverse

这是我做reverse的题解。在咱逆向之路上的mark一下&#xff0c;&#xff0c;水平有限&#xff0c;大牛见笑。题目及题解链接&#xff1a;http://pan.baidu.com/s/1gd3k2RL 宗女齐姜 果然是仅仅有50分的难度&#xff0c;OD直接找到了flag. 找到杀手 这题用OD做非常麻烦。我改用I…

DevOps平台中的自动化部署框架设计

本文目录&#xff1a; 一、背景 二、我们的需求是什么&#xff1f; 三、概念澄清 四、概念模型 五、总体设计 六、关键点设计 七、总结 一、背景 说到自动化部署&#xff0c;大家肯定都会想到一些配置管理工具&#xff0c;像ansible,chef,puppet, saltstack等等。虽然这些工具给…

胃癌2019csco指南_2019 CSCO胃癌诊疗指南精华来了!

一文轻松get 2019 CSCO胃癌诊疗指南更新要点&#xff01;文丨青青子衿 中山大学肿瘤防治中心来源丨医学界肿瘤频道近日&#xff0c;2019年CSCO指南发布会于南京召开。今天为大家推送的是2019 CSCO胃癌诊疗指南的最新更新&#xff0c;在发布专场中&#xff0c;来自华中科技大学同…

learn opengl 中文_LearnOpenGL CN

欢迎来到OpenGL的世界欢迎来到OpenGL的世界。这个工程只是我(Joey de Vries)的一次小小的尝试&#xff0c;希望能够建立起一个完善的OpenGL教学平台。无论你学习OpenGL是为了学业&#xff0c;找工作&#xff0c;或仅仅是因为兴趣&#xff0c;这个网站都将能够教会你现代(Core-p…

MYSQL5.7 日志管理

2019独角兽企业重金招聘Python工程师标准>>> 慢查询日志slow-query-log1 slow-query-log-filefile_name long_query_time1 #SQL执行多长时间以上会记录到慢查询日志&#xff0c;0~10s log_slow_admin_statementsOFF #在写入慢查询日志的语句中包含缓慢的管理语句。 …

cad导出 dxf后中文不显示_CAD快速看图 for Mac

CAD快速看图 for Mac是一款非常小巧、快速、方便的DWG看图工具&#xff0c;CAD快速看图 Mac版可脱离AutoCAD最快速、最方便浏览DWG和DXF图纸&#xff0c;支持二维或三维图纸&#xff0c;支持高清、多文件和云字体&#xff0c;非常实用的一款CAD看图软件&#xff0c;CAD快速看图…

关于java.util.ConcurrentModificationException和remove倒数第二个元素

2019独角兽企业重金招聘Python工程师标准>>> 首先是两段代码的执行结果&#xff1a; 代码一&#xff1a; public class TestListRemove {public static void main(String[] args) {List<Integer> list new ArrayList<Integer>();list.add(1);list.add(…

怎么删除mysql的压缩包_压缩包版mysql怎么卸载

MySQL是一个小巧玲珑但功能强大的数据库&#xff0c;目前十分流行。但是官网给出的安装包有两种格式&#xff0c;一个是msi格式&#xff0c;一个是zip格式的。那么压缩版mysql要怎么卸载&#xff1f;下面本篇文章就来大家介绍一下&#xff0c;希望对你们有所帮助。卸载压缩包版…

lambda表达式之进化

前言在C#我们可以自定义委托&#xff0c;但是C#为什么还要内置泛型委托呢&#xff1f;因为我们常常要使用委托&#xff0c;如果系统内置了一些你可能会用到的委托&#xff0c;那么就省去了定义委托&#xff0c;然后实例化委托的步骤&#xff0c;这样一来既使代码看起来简洁而干…

mysql返回行数_如何计算MySQL查询返回的行数?

How can I count the number of rows that a MySQL query returned?解决方案Getting total rows in a query result...You could just iterate the result and count them. You dont say what language or client library you are using, but the API does provide a mysql_nu…

md5不是对称密码算法_密码学中的消息摘要算法5(MD5)

md5不是对称密码算法In cryptography, MD5 (Message-Digest algorithm 5) is a mainly used cryptographic hash function with a 128-bit hash value. As we use in an Internet standard (RFC 1321), MD5 has been employed or developed in a more variety of security appl…

Windows 7 SID 修改

在安裝Windows系統時會產生一個獨一無二的SID (Security ID)&#xff0c;它用來識別每一部主機&#xff0c;若在同一個區域網路內有兩部相同SID的主機&#xff0c;會出現警告訊息。一般而言&#xff0c;每次安裝時的SID不可能會發生重複&#xff0c;但若是使用TrueImage或Ghost…

1 并发模型

并发系统可以采用多种并发编程模型来实现。并发模型指定了系统中的线程如何通过协作来完成分配给它们的作业。不同的并发模型采用不同的方式拆分作业&#xff0c;同时线程间的协作和交互方式也不相同。这篇并发模型教程将会较深入地介绍目前&#xff08;2015年&#xff0c;本文…

mysql log4jlogger_mybatis结合log4j打印SQL日志

mybatis结合log4j打印SQL日志1.Maven引用jar包默认的mybatis不能打印出SQL日志&#xff0c;不便于查看调试&#xff0c;须要结合log4jdbc-log4j2就能够完整的输入SQL的调试信息。pom.xml 配置maven。注意以下3个都须要org.bgee.log4jdbc-log4j2log4jdbc-log4j2-jdbc4.11.16org.…

cellpadding_在CSS中设置cellpadding和cellspacing

cellpaddingIntroduction: 介绍&#xff1a; It is not unknown anymore that now and then we make use of tables in our web page or website, therefore we all are familiar with how to create tables or grids in our website or web page but there are times when we…

mongodb 排序_技术分享 | MongoDB 一次排序超过内存限制的排查

本文目录&#xff1a;一、背景1. 配置参数检查2. 排序字段是否存在索引二、测试环境模拟索引对排序的影响1. 测试环境信息2. 报错语句的执行计划解释 3. 建立新的组合索引进行测试三、引申的组合索引问题1. 查询语句中&#xff0c;排序字段 _id 使用降序2. 查询语句中&#xff…

spark源码分析之Executor启动与任务提交篇

任务提交流程 概述 在阐明了Spark的Master的启动流程与Worker启动流程。接下继续执行的就是Worker上的Executor进程了&#xff0c;本文继续分析整个Executor的启动与任务提交流程Spark-submit 提交一个任务到集群通过的是Spark-submit通过启动脚本的方式启动它的主类&#xff0…

mysql 5.5.22.tar.gz_MySQL 5.5.22源码编译安装

MySQL 最新的版本都需要cmake编译安装&#xff0c;估计以后的版本也会采用这种方式&#xff0c;所以特地记录一下安装步骤及过程&#xff0c;以供参考。注意&#xff1a;此安装是默认CentOS下已经安装了最新工具包&#xff0c;比如GNU make, GCC, Perl, libncurses5-dev&#x…

利用python进行数据分析D2——ch03IPython

为无为,事无事,味无味。大小多少,报怨以德。图难于其易,为大于其细;天下难事必作于易,天下大事必作于细。——老子关于图片的例子&#xff1a;import matplotlib.pyplot as plt imgplt.imread(ch03/stinkbug.png) import pylab plt.imshow(img) pylab.show()结果&#xff1a;调…

mysql 视图 字典_MySQL深入01-SQL语言-数据字典-服务器变量-数据操作DML-视图

SQL语言的组成部分常见分类&#xff1a;DDL&#xff1a;数据定义语言DCL&#xff1a;数据控制语言&#xff0c;如授权DML&#xff1a;数据操作语言其它分类&#xff1a;完整性定义语言&#xff1a;DDL的一部分功能约束约束&#xff1a;包括主键&#xff0c;外键&#xff0c;唯一…