DOM(四)——事件、事件模型(冒泡)与事件对象的功能
文章目录
- 一、事件
- 二、 事件绑定
- 1. 在HTML中手工绑定
- 2. 在js中以赋值方式绑定
- 3. 在js中以添加事件监听对象的方式绑定:
- 3.1 原理
- 3.2 移除事件监听对象
- 三、事件模型
- 四、事件对象
- 4.1 功能
- a. 停止冒泡: `e.stopPropagation()`
- b.利用冒泡/事件委托
- c. 阻止默认行为
- d. 取鼠标位置: 3组坐标
一、事件
事件:浏览器自动触发的或用户手动触发的页面中内容或状态的改变
事件处理函数: 当事件发生时,我们希望自动调用执行的函数
事件绑定:
a. 每个元素上都有一批on开头的事件属性b. 事件绑定就是提前将事件处理函数保存到元素的事件属性上。
c. 结果: 当事件发生时
1). 浏览器先找到元素身上的对应事件属性
2). 再自动调用事件属性中保存的事件处理函数
二、 事件绑定
1. 在HTML中手工绑定
<元素 on事件名="事件处理函数()">
<script>function 事件处理函数(){ ... }
</script>
缺点:麻烦,不便于今后维护
2. 在js中以赋值方式绑定
步骤:
- 查找触发事件的元素对象
- 绑定事件:
元素对象.on事件名=function(){ ... this ... }
缺点: 无法给一个元素的一个事件属性同时绑定多个事件处理函数,后赋值的事件处理函数会把原事件处理函数覆盖。
3. 在js中以添加事件监听对象的方式绑定:
步骤:
查找触发事件的元素
添加事件监听对象:
元素对象.addEventListener("事件4名", 事件处理函数)
tip:
1.添加事件监听时,事件名称不要加on前缀
其实,DOM标准中事件名本来是没有on的!
比如: click, blur, change
元素对象中为了将事件属性和其它普通属性区分开,便于识别,才在事件属性名前加on。
2.添加事件监听对象时,事件处理函数结尾不要加()!
因为事件处理函数都不是立刻执行!而是将来某个时间,触发事件时,才自动调用执行。
示例:
<button id="btnShoot">shoot</button><br>
<button id="btnAward">获得跟踪导弹</button><br><script>var btnShoot = document.getElementById("btnShoot");var btnAward = document.getElementById("btnAward");//开局: 点btnShoot只能发射普通子弹btnShoot.onclick = function () {console.log(`发射普通子弹......`)}//如果发现跟踪导弹有可能被移除,就要定义为有名称的函数var shoot2=function () {console.log(`发射跟踪导弹=>=>=>`);}//点btnAward可以为btnShoot再添加一种新的跟踪导弹btnAward.onclick = function () {// btnShoot.οnclick=function(){btnShoot.addEventListener("click",//绑定时必须用函数名shoot2)}
</script>
3.1 原理
浏览器中有一个巨大的事件监听对象队列
. addEventListener
做了2件事:
i. 新建一个事件监听对象,其中保存:元素对象、事件名、事件处理函数
ii. 自动将事件监听对象添加到事件监听对象队列中。
重复执行几次
addEventListener()
就会反复添加几个重复的事件监听对象将来事件发生时:
i. 浏览器先查找元素对象自己身上的事件属性中保存的事件处理函数,优先自动执行.
ii. 然后浏览器才会去事件监听对象队列中遍历查找所有符合要求(元素相同,事件名也相同)的事件监听对象。
找到几个,就触发几个事件处理函数。
3.2 移除事件监听对象
元素.removeEventListener("事件名", 原事件处理函数)
今后只要一个事件监听对象有可能被移除,则绑定时就不要用匿名函数。
绑定时就必须用有名称的函数。移除监听对象时,也用函数名移除.
示例:
<button id="btnBreak">失去跟踪导弹</button><br><script>var btnBreak = document.getElementById("btnBreak");var shoot2=function () {console.log(`发射跟踪导弹=>=>=>`);}btnBreak.onclick=function(){btnShoot.removeEventListener("click",//移除时只有通过函数名才能获得原函数对象shoot2)}
</script>
问题:
一旦绑定时,使用有名称的函数添加事件监听,则完全相同的事件监听对象只能添加一个。
解决:
i. 自己用数组保存所有事件处理函数
ii. jq中解决
三、事件模型
事件模型: 点在内层元素上,也相当于点在了外层元素上。所以,就有了事件模型。
3个阶段:
1) 捕获:
从树根节点开始,到当前触发事件的目标元素结束,由外向内依次遍历并记录各级父元素上是否绑定了事件处理函数。只记录,不执行!
2) 目标触发:
总是优先触发实际点击的目标元素上的事件处理函数。
目标元素(target): 实际点击到的那个元素
3) 冒泡:
从目标元素开始,到树根节点结束,由内向外依次触发各级父元素上绑定的事件处理函数。
示例: 点内层元素,也触发父元素上的事件处理函数:
<style type="text/css">div {/* 定义div元素样式 */margin: 20px; /* 边界距离 */border: solid 1px blue; /* 蓝色边框线 */font-size: 18px; /* 字体大小 */}
</style> <div class="div-1">div-1<div class="div-2">div-2<div class="div-3">div-3<div class="div-4">div-4<div class="div-5">div-5</div></div></div></div>
</div>
<p id="show"></p><script>function bubble() {var div = document.getElementsByTagName('div');var show = document.getElementById("show");for (var i = 0; i < div.length; ++i) { //遍历div元素div[i].onclick = (function(i) { //为每个div元素注册鼠标单击事件处理函数return function() { //返回闭包函数div[i].style.border = '1px dashed red'; //定义当前元素的边框线为红色虚线show.innerHTML += div[i].className + " > "; //标识每个div元素的响应顺序:div5>div4>div3>div2>div1}})(i);}}window.onload = bubble;
</script>
初始:
当点击div-4区域内空白位置时,触发事件处理函数的顺序为:div-4 > div-3 > div-2 > div-1
停止冒泡请看下文……
四、事件对象
事件对象:当事件发生时,浏览器自动创建的,保存事件相关信息的对象。
适用:
a. 想获得事件相关的信息时
b. 想改变事件默认的行为
步骤:
- 事件对象总是作为事件处理函数的第一个实参值,自动传入
- 所以:
//当事件发生时
//浏览器自动创建事件对象event
↓
元素对象.on事件名=function( e ){ … }
或
元素对象.addEventListener(“事件名”,function(e){ … })
4.1 功能
a. 停止冒泡: e.stopPropagation()
如果我们在使用的时候不想使用冒泡事件模型,就要借助事件对象来停止冒泡:
将上述代码中的script内容改为:
在回调函数中传入事件对象e,并使用e.stopPropagation();
方法即可
<script>
function bubble() {var div = document.getElementsByTagName('div');var show = document.getElementById("show");for (var i = 0; i < div.length; ++i) { //遍历div元素div[i].onclick = (function(i) { //为每个div元素注册鼠标单击事件处理函数return function(e) {//返回闭包函数,并传入事件对象ediv[i].style.border = '1px dashed red'; //定义当前元素的边框线为红色show.innerHTML += div[i].className + " > \n" ;e.stopPropagation();}})(i);}
}
window.onload = bubble;
</script>
b.利用冒泡/事件委托
浏览器触发事件:遍历事件监听对象队列形式查找事件监听对象。
如果添加的事件监听对象越多,遍历时间越长,事件响应的速度越慢
优化:应在保持功能的情况下尽量减少事件绑定的次数
步骤:
当多个子元素都要绑定相同的事件处理函数时,只要给父元素绑定一个事件处理函数即可
所有子元素都可通过冒泡的方式触发父元素上统一的事件处理函数——共用!
缺点:
事件处理函数绑定在父元素上的,触发也是在父元素上触发的,this->父元素,不再指子元素。
再使用this,就无法获得实际点击的子元素了。只要使用事件委托,都要用
e.target
代替this
e.target
: 是事件对象中专门保存最初点击的那个目标元素的特殊属性。
优点: 不随冒泡而改变先验证当前点击的目标元素的特征,只有目标元素的特征符合要求,才继续执行后续操作,否则不执行操作
一切目标元素与其他元素不同的特征,都可作为判断依据
.className,.nodeName,.name, ... ...
示例:
<ul id="list"><li>列表项目1</li><li>列表项目2</li><li>列表项目3</li>
</ul><script>var ul = document.getElementById("list");ul.addEventListener('click',function(e) {var e = e || window.event; //兼容事件对象var target = e.target || e.srcElement; //兼容事件目标元素if (e.target&&e.target.nodeName.toUpperCase()=="LI") {/*判断目标事件是否为li*/alert(e.target.innerHTML);}});
</script>
c. 阻止默认行为
有些HTML元素身上带有我们不想要的默认行为。
例:a会自动在地址栏url结尾添加#,不是我们想要的
<a href="#">仅当做按钮用的a</a>
解决:
<a href="javascript:;">文本</a>
只对a元素有效- href中的
javascript
意思是不让a跳转到其它页面,而是在当前页面的内容中执行一条js语句。 ;
意为是一条什么也不做的空语句javascript:;
合起来表示执行一条空语句,相当于什么也不做。
- href中的
e.preventDefault()
对 任意元素 都有效
示例: 点a可返回顶部,但不在地址栏结尾加#top
<a id="a1" href="#top">返回顶部</a><script>var a1=document.getElementById("a1");a1.onclick=function(e) {// 滚动 到 0位置window.scrollTo(0,0);e.preventDefault();//阻止默认行为,适用于所有元素}
</script>
d. 取鼠标位置: 3组坐标
1). 鼠标相对于屏幕左侧、上方的距离
e.screenX, e.screenY
2). 鼠标相对于浏览器内部文档显示区左侧、上方的距离
e.clientX, e.clientY
3). 鼠标相对于当前点击的HTML元素左侧、上方的距离
e.offsetX, e.offsetY
DOM(四)——事件、事件模型(冒泡)与事件对象的功能相关推荐
- Silverlight实用窍门系列:35.细解Silverlight冒泡路由事件和注册冒泡路由事件【附带实例源码】...
Silverlight中的事件分为普通事件和冒泡路由事件,它并没有包括WPF中的隧道路由事件,在本章中将详细讲解冒泡路由事件和如何注册一个冒泡路由事件. 一.细解冒泡路由事件 冒泡路由事件可以比喻为: ...
- 你真的理解事件绑定、事件冒泡和事件委托吗?
一文了解Web API中的事件绑定.事件冒泡.事件委托 引言 正文 一.事件绑定 1.事件和事件绑定时什么? 2.事件是如何实现的? 二.事件冒泡 1.事件模型 2.事件模型解析 (1)捕获阶段 (2 ...
- 三种方式实现观察者模式 及 Spring中的事件编程模型
观察者模式可以说是众多设计模式中,最容易理解的设计模式之一了,观察者模式在Spring中也随处可见,面试的时候,面试官可能会问,嘿,你既然读过Spring源码,那你说说Spring中运用的设计模式吧, ...
- 面试题7:Js事件流,事件冒泡(IE事件流)
事件流 在第四代 Web 浏览器(IE4 和 Netscape Communicator 4)开始开发时,开发团队碰到了一个有意思的问题:页面哪个部分拥有特定的事件呢?要理解这个问题,可以在一张纸上画 ...
- JS不支持冒泡的事件
1.UI事件: loadunloadscrollresize 2.焦点事件 : blurfocus 3.鼠标事件: mouseleavemouseenter 冒泡的事件解释: 当事件发生后,这个事件就 ...
- 事件模型、事件流(冒泡与捕获)、事件代理
本文原链接:https://www.cnblogs.com/hngdlxy143/p/9068282.html https://www.jb51.net/article/139997.htm 事件模型 ...
- “约见”面试官系列之常见面试题第三十四篇之事件冒泡、事件捕获、事件代理(建议收藏)
对于事件的传播机制,Netscape Communicator采用的是事件捕获(event capture),IE9.Safari.Chrome.Opera和Firefox采用的是事件冒泡(event ...
- 事件链、事件代理、页面的渲染过程、style的操作、防抖与节流【DOM(四)】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 目录 文章目录 1.事件链(冒泡目标捕获) (1)事件链原理 (2)阻止冒泡和默认事件 2.事件代理(面试笔试题重点) 3. ...
- Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托机制
一.事件的捕获与冒泡 由W3C规定的DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡,在捕获和冒泡阶段,会依次检查途径的每个节点,如果该节点注册了相应的监听函数,则执行监 ...
最新文章
- 调查用QQ企业邮箱的smtp需要添加spf1
- 编程前在Pycharm中自动添加时间日期作者等信息
- python第三方库大全win-Python标准库、第三方库和外部工具汇总
- Python 卡方检验演算
- EA和Take-Two游戏业巨头纷纷陷入困境
- [CXF REST标准实战系列] 一、JAXB xml与javaBean的转换(转)
- 安卓学习笔记15:使用安卓应用程序资源
- 编译SOCI-3.1.0 开启sqlite3支持
- 《Head First Servlets JSP》-11-Web应用部署
- 关于rocketmq的配置启动
- CAJ VIEWER 7.2 已停止工作(正确的处理方法,最快最正确的方法,网上的其他方法也就是看看,很难找到问题的正确办法)
- html仿百度贴吧,利用Canvas模仿百度贴吧客户端loading小球的方法示例
- h264封装ts文件资料相关
- OCT-模拟电路设计八边形法则的探讨
- Android 消息通知栏用法详解(一)
- 这可能是你能找到最全面的数据预处理介绍
- 2019第二届中国天津国际智慧消防高峰论坛
- [二分查找] [luoguP3500] [POI2010] TES-Intelligence Test
- php毕业论文致谢,毕业论文致谢词(看完这条,你的论文致谢词不用愁了)
- 洛谷 P5197 [USACO19JAN]Grass Planting 题解
热门文章
- Linux下执行.sh文件
- Python开发【第二篇】:Python基本数据类型
- CF #371 (Div. 2) C、map标记
- jquery.cookie中的操作
- Android自动化测试之路——技术准备
- http://sourceforge.net/projects/rtspdirectshow/
- 删除VisaulStudio2010产生的垃圾
- DX10 Shadow Volumn Sample Code的Bug修正
- 【转】Visual Studio 2005/2008中的快捷键与小技巧整理
- [Math]添加了一个EulerProject标志