文章目录

  • 一、事件
  • 二、 事件绑定
    • 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中以赋值方式绑定

步骤:

  1. 查找触发事件的元素对象
  2. 绑定事件: 元素对象.on事件名=function(){ ... this ... }

缺点: 无法给一个元素的一个事件属性同时绑定多个事件处理函数,后赋值的事件处理函数会把原事件处理函数覆盖。

3. 在js中以添加事件监听对象的方式绑定:

步骤:

  1. 查找触发事件的元素

  2. 添加事件监听对象: 元素对象.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 原理

  1. 浏览器中有一个巨大的事件监听对象队列

  2. . addEventListener做了2件事:
         i. 新建一个事件监听对象,其中保存:元素对象、事件名、事件处理函数
         ii. 自动将事件监听对象添加到事件监听对象队列中

  3. 重复执行几次addEventListener()就会反复添加几个重复的事件监听对象

  4. 将来事件发生时:
        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. 想改变事件默认的行为

步骤:

  1. 事件对象总是作为事件处理函数的第一个实参值,自动传入
  2. 所以:
    //当事件发生时
    //浏览器自动创建事件对象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.利用冒泡/事件委托

浏览器触发事件:遍历事件监听对象队列形式查找事件监听对象。
如果添加的事件监听对象越多,遍历时间越长,事件响应的速度越慢

优化:应在保持功能的情况下尽量减少事件绑定的次数

步骤:

  1. 当多个子元素都要绑定相同的事件处理函数时,只要给父元素绑定一个事件处理函数即可
    所有子元素都可通过冒泡的方式触发父元素上统一的事件处理函数——共用!
    缺点:
    事件处理函数绑定在父元素上的,触发也是在父元素上触发的,this->父元素,不再指子元素
    再使用this,就无法获得实际点击的子元素了。

  2. 只要使用事件委托,都要e.target代替this
    e.target: 是事件对象中专门保存最初点击的那个目标元素的特殊属性。
    优点: 不随冒泡而改变

  3. 验证当前点击的目标元素的特征,只有目标元素的特征符合要求,才继续执行后续操作,否则不执行操作
    一切目标元素与其他元素不同的特征,都可作为判断依据
    .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元素有效

    1. href中的javascript意思是不让a跳转到其它页面,而是在当前页面的内容中执行一条js语句。
    2. ; 意为是一条什么也不做的空语句
    3. javascript:; 合起来表示执行一条空语句,相当于什么也不做。
  • 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(四)——事件、事件模型(冒泡)与事件对象的功能相关推荐

  1. Silverlight实用窍门系列:35.细解Silverlight冒泡路由事件和注册冒泡路由事件【附带实例源码】...

    Silverlight中的事件分为普通事件和冒泡路由事件,它并没有包括WPF中的隧道路由事件,在本章中将详细讲解冒泡路由事件和如何注册一个冒泡路由事件. 一.细解冒泡路由事件 冒泡路由事件可以比喻为: ...

  2. 你真的理解事件绑定、事件冒泡和事件委托吗?

    一文了解Web API中的事件绑定.事件冒泡.事件委托 引言 正文 一.事件绑定 1.事件和事件绑定时什么? 2.事件是如何实现的? 二.事件冒泡 1.事件模型 2.事件模型解析 (1)捕获阶段 (2 ...

  3. 三种方式实现观察者模式 及 Spring中的事件编程模型

    观察者模式可以说是众多设计模式中,最容易理解的设计模式之一了,观察者模式在Spring中也随处可见,面试的时候,面试官可能会问,嘿,你既然读过Spring源码,那你说说Spring中运用的设计模式吧, ...

  4. 面试题7:Js事件流,事件冒泡(IE事件流)

    事件流 在第四代 Web 浏览器(IE4 和 Netscape Communicator 4)开始开发时,开发团队碰到了一个有意思的问题:页面哪个部分拥有特定的事件呢?要理解这个问题,可以在一张纸上画 ...

  5. JS不支持冒泡的事件

    1.UI事件: loadunloadscrollresize 2.焦点事件 : blurfocus 3.鼠标事件: mouseleavemouseenter 冒泡的事件解释: 当事件发生后,这个事件就 ...

  6. 事件模型、事件流(冒泡与捕获)、事件代理

    本文原链接:https://www.cnblogs.com/hngdlxy143/p/9068282.html https://www.jb51.net/article/139997.htm 事件模型 ...

  7. “约见”面试官系列之常见面试题第三十四篇之事件冒泡、事件捕获、事件代理(建议收藏)

    对于事件的传播机制,Netscape Communicator采用的是事件捕获(event capture),IE9.Safari.Chrome.Opera和Firefox采用的是事件冒泡(event ...

  8. 事件链、事件代理、页面的渲染过程、style的操作、防抖与节流【DOM(四)】

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 目录 文章目录 1.事件链(冒泡目标捕获) (1)事件链原理 (2)阻止冒泡和默认事件 2.事件代理(面试笔试题重点) 3. ...

  9. Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托机制

    一.事件的捕获与冒泡 由W3C规定的DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡,在捕获和冒泡阶段,会依次检查途径的每个节点,如果该节点注册了相应的监听函数,则执行监 ...

最新文章

  1. 调查用QQ企业邮箱的smtp需要添加spf1
  2. 编程前在Pycharm中自动添加时间日期作者等信息
  3. python第三方库大全win-Python标准库、第三方库和外部工具汇总
  4. Python 卡方检验演算
  5. EA和Take-Two游戏业巨头纷纷陷入困境
  6. [CXF REST标准实战系列] 一、JAXB xml与javaBean的转换(转)
  7. 安卓学习笔记15:使用安卓应用程序资源
  8. 编译SOCI-3.1.0 开启sqlite3支持
  9. 《Head First Servlets JSP》-11-Web应用部署
  10. 关于rocketmq的配置启动
  11. CAJ VIEWER 7.2 已停止工作(正确的处理方法,最快最正确的方法,网上的其他方法也就是看看,很难找到问题的正确办法)
  12. html仿百度贴吧,利用Canvas模仿百度贴吧客户端loading小球的方法示例
  13. h264封装ts文件资料相关
  14. OCT-模拟电路设计八边形法则的探讨
  15. Android 消息通知栏用法详解(一)
  16. 这可能是你能找到最全面的数据预处理介绍
  17. 2019第二届中国天津国际智慧消防高峰论坛
  18. [二分查找] [luoguP3500] [POI2010] TES-Intelligence Test
  19. php毕业论文致谢,毕业论文致谢词(看完这条,你的论文致谢词不用愁了)
  20. 洛谷 P5197 [USACO19JAN]Grass Planting 题解

热门文章

  1. Linux下执行.sh文件
  2. Python开发【第二篇】:Python基本数据类型
  3. CF #371 (Div. 2) C、map标记
  4. jquery.cookie中的操作
  5. Android自动化测试之路——技术准备
  6. http://sourceforge.net/projects/rtspdirectshow/
  7. 删除VisaulStudio2010产生的垃圾
  8. DX10 Shadow Volumn Sample Code的Bug修正
  9. 【转】Visual Studio 2005/2008中的快捷键与小技巧整理
  10. [Math]添加了一个EulerProject标志