事件冒泡与事件捕获

本文解析了事件流中的事件冒泡和事件捕获两种机制,并通过实例展示了这两种机制的区别及其在实际开发中的应用。

导语:当浏览器发展到第四代时(IE4和Netscape Communicator4),浏览器开发团队遇到了一个很有趣的问题:页面的哪一部分会拥有某个特定的事件?要明白这个问题问的是什么,可以想象画在同一张纸上的一组同心圆。如果你把手指放在圆心上,那么你手指指向的不是一个圆。两家公司的浏览器开发团队在看待浏览器事件方面还是一致的。如果你单击了某个按钮,他们都认为单击事件不仅仅发生在按钮上。换句话说,在单击按钮的同事,你也单击了按钮的容器元素,甚至也单击了整个页面。
问题引入: 事件流描述的是页面中接收事件的顺序。但是有意思的是,IE和Netscape开发团队居然提出了差不多是完全相反的事件流的概念。IE的事件流是事件冒泡流,Netscape的事件流是事件捕获流。

1.概念

以下面的HTML页面作为实例:

<!DOCTYPE html>
<html>
<head>
    <title>Event Bubbling and Event Capturing</title>
</head>
<body>
    <div id="muDiv">Click Me</div>
</body>
</html>
1.1事件冒泡(event bubbling):事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)开始,然后逐级向上传播到较为不具体的元素(文档)。

如果你点击了页面中的div元素,那么这个click事件会按照如下顺序传播:
<div>-><body>-><html>->document
也就是说,点击事件首先在<div>元素上发生,而这个元素就是我们单击的元素。然后,click事件沿DOM树逐层向上传播,在每一级节点上都会发生,直到传播到document对象。

1.2事件捕获:不太具体的元素更早接收到事件,而最具体的元素最后接收到事件。

如果你点击div元素,会以下列顺序触发click事件:
document-><html>-><body>-><div>
也就是说,document对象首先接收到click事件,然后事件沿DOM树依次向下,直到传播到事件的实际目标,及<div>元素。
由于一些老版本浏览器的不支持,因此很少有人用事件捕获。建议大家用事件冒泡,特殊需要的话用事件捕获。

2.事件的绑定

addEventListener()方法为对象绑定事件:它接收三个参数(要处理的事件名,作为事件处理程序的函数,一个布尔值)。如果最后这个布尔值的值为true时,表示在捕获阶段调用事件处理程序;如果为false,表示在冒泡阶段调用事件处理程序。默认为false。
HTML结构如下:

<div id="parent">
        <p id="child">点击此处有彩蛋</p>
</div>
2.1事件冒泡:

Js代码:

       document.getElementById('parent').addEventListener("click",function () {
                alert("parent事件被触发,"+this.id);
            });
       document.getElementById('child').addEventListener("click",function () {
                alert("child事件被触发,"+this.id);
            });  

执行结果:

child事件被触发,child
parent事件被触发,parent

解释:第三个参数没写,默认为false,在捕获阶段调用函数,id为child的元素先接收到该事件,再沿DOM树向上冒泡,id为parent的元素也接收到该事件,所以先输出child的,再输出parent的。

2.2事件捕获:

Js代码:

document.getElementById('parent').addEventListener("click",function () {
                alert("parent事件被触发,"+this.id);
            },true);
document.getElementById('child').addEventListener("click",function () {
                alert("child事件被触发,"+this.id);
            },true);

执行结果:

parent事件被触发,parent
child事件被触发,child

解释:第三个参数为true,表示在事件捕获阶段执行该函数。id为parent的元素先接受到这个事件,然后沿DOM树依次向下,id为child的元素再接受到该事件。


注意: IE浏览器不支持事件捕获,只支持事件冒泡,也没有addEventListener()方法,他提供了另一个方法,attachEvent(),接收两个参数,一个是事件名称(名称前要加on),另一个是事件处理函数。通过attachEvent()方法添加的事件处理程序都会被添加到冒泡阶段。
附: addEventListener()方法为绑定事件,对应的删除事件为removeEventListener()。通过前者添加的事件只能通过后者来删除,删数时传入的参数与添加时的参数一样,也就是说,通过addEventListener()添加的匿名函数无法移除!整一段代码看看:

var btn=document.getElementById("btn");
btn.addEventListener("click",function(){
    alert(this.id);
});   /*b绑定了一个click事件*/
btn.removeEventListener("clcik",function(){
    alert(this.id);
});   /*移除这个事件,然而移除不了。。。*/

虽然看起来和绑定时候的参数一样,但是第二个参数与传入addEventListener()的是完全不同的函数!所以给函数起个名字吧,没有名字怪可怜的…

var btn=document.getElementById("btn");
function aaa(){
    alert(this.id);
}
btn.addEventListener("click",aaa);
btn.removeEventListener("click",aaa);

这样不就万事大吉了?!!

3.应用

<ul>
     <li>item1</li>
     <li>item2</li>
     <li>item3</li>
     <li>item4</li>
     <li>item5</li>
     <li>item6</li>
</ul>

要求:鼠标放到li上对应的li背景变灰

3.1利用事件捕获实现:
$("ul").on("mouseover",function(e){
    $(e.target).css("background-color","#ddd").siblings().css("background-color","white");
});

代码解释:给ul绑定onmouseover事件(注意:当用jQuery中的on方法时,事件名称前面不加on,js中的addEventListener方法中的第一个参数方法名也不加on),传入一个事件的参数e,e.target指的就是这个事件的目标元素,也就是li(会在下文中详细解释),把目标元素调用css方法,改变其背景颜色,将它的兄弟节点的背景颜色改为白色。这样就实现了鼠标放在哪个li上面哪个li的颜色变为灰色。
为何说使用时间冒泡实现的呢?是因为我们在ul上面绑定了事件,当我们鼠标放在ul的子对象也就是li上面的时候,会由该元素向上冒泡到ul,执行ul的事件绑定函数。当用语句$("<li>item7</li>").appendTo("ul"); 向ul动态添加一个li元素,鼠标放在该元素上面,没有函数可执行,然后沿DOM树向上冒泡,找到ul,执行ul绑定的事件的函数。

3.2利用普通方法实现:
$("li").on("mouseover",function(e){
    $(this).css("background-color","#ddd").siblings().css("background-color","white");
});

代码解释:直接获取到li元素,给每个li元素都绑定了这样的一个事件,当你动态添加一个li节点时,由于并没有给这个绑定事件,所以不会有效果。因为js代码从上到下执行,执行到绑定事件那块,就给这个页面现有的li绑定了这个事件,而新增加的节点的代码还没有加载进来,所以这个li不会绑定事件,只是添加进来一个节点而已…

4.e.target、e.currentTarget 和this

直接上代码,简单粗暴(自动脑补一个斜眼笑的表情)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #parent{
            width:200px;
            height:100px;
            background-color: lightsalmon;
        }
        #child{
            width:100px;
            height:50px;
            background-color: powderblue;
        }
    </style>
</head>
<body>
    <div id="parent" onclick="getEventTrigger(event)">
        <div id="child" onclick="getEventTrigger(event)">来点我呀?!</div>
    </div>
    <script>
        function getEventTrigger(e) {
            var x=e.currentTarget;
            var y=e.target;
            alert("currentTarget指向:"+x.id+"        target指向:"+y.id);
        }
    </script>
</body>
</html>

运行结果:
1.点击parent:
点击parent
解释:由于默认为事件冒泡,所以点击parent,先触发id为parent的这个元素的事件,它的currentTarget就是当前的这个节点,它的target也是当前的这个节点。
2.点击child:
child1
这里写图片描述
解释:点击child这个元素,事件监听的对象是child这个元素,目标也是这个元素,currentTarget就是child,target也是这个元素。执行完child这个元素上的事件后,冒泡到它的父元素,监听的对象就是parent,而目标元素依然是child这个元素。
通俗一点就是,e.currentTarget是注册了事件监听的对象,而e.target是该对象里的子对象,也就是触发了这个事件的对象。

关于this:
<div id="parent" onclick="alert(this.id)">
    <div id="child" onclick="alert(this.id)">来点我呀?!</div>
</div>

执行结果:
1.点击父元素:弹出parent
2.点击子元素:弹出child,弹出parent
解释:
1.点击parent,this指的就是当前绑定click事件的这个对象,弹出它的id,冒泡上去,也没什么。。
2.点击child,this先指向child这个元素,因为默认是事件冒泡嘛,所以弹出child,然后向上冒泡,在parent元素上也触发这个事件,this就指向parent这个元素,弹出它的id。一句话来说,this和currentTarget是一样的。

附:参考的资料
http://www.cnblogs.com/qq9694526/p/5653728.html
http://blog.csdn.net/magic__man/article/details/51781425
JavaScript高级程序设计(第三版)

Beyond Compare是一款文件差异比较工具的文件和文件夹比较工具,使用该工具可以可视化和调整差异, 合并修改,同步文件夹。支持文件夹比较,文件夹合并和同步,文本比较,表格比较,图片比较,16进制比较,注册表比较,版本比较等;调整差异,合并修改,内置文件浏览器可以针对文件、文件夹之间的差异对比及上传同步。 Beyond Compare 5.0.4.30422是一款先进的文件和文件夹比较工具,它能够帮助用户高效地识别和管理文件差异,支持多种文件类型和格式的比较。使用Beyond Compare,用户可以轻松地对文件夹内容进行同步,无论是进行简单的文件复制还是复杂的项目同步任务。此外,该工具还具备了高级的文件比较功能,如文本比较、表格比较、图片比较、16进制比较以及注册表比较,覆盖了从纯文本到二进制文件的广泛使用场景。 对于文本文件的比较,Beyond Compare提供了语法高亮和行号等辅助功能,让用户在审查代码或文档时能更快地定位差异点。表格比较功能则特别适用于数据分析和处理任务,可以快速识别两个Excel电子表格之间的不同之处。在进行图片文件的比较时,用户可以通过直观的视图了解图片之间的微小差别,这在图像处理和质量控制中尤其有用。 此外,16进制比较功能为开发者提供了深入分析二进制文件差异的手段,无论是在软件开发还是在数据恢复方面都大有裨益。注册表比较则专注于Windows系统的核心配置文件,帮助IT专业人员快速定位系统配置的变化,这对于系统维护和故障排除尤其重要。 Beyond Compare内置的文件浏览器允许用户在一个界面内完成文件的浏览、比较和同步操作,极大的提高了工作效率。内置的差异调整和合并修改功能让同步文件夹的工作更加精确和便捷。用户可以针对不同的文件和文件夹进行个性化设置,实现定制化的比较和同步策略。
内容概要:本文介绍了一种基于Simulink的发电机故障暂态仿真模型,旨在深入研究发电机在发生各类短路故障(如单相接地、两相短路接地及两相相间短路)时电压电流的动态变化特性。该模型精确构建了发电机及其保护系统的电气结构,能够有效模拟故障瞬间的暂态响应过程,全面分析不同接地方式(中性点不接地、经小电阻接地、经消弧线圈接地)对系统电气量的影响。通过仿真获取的电压、电流波形数据,可用于评估电力系统的暂态稳定性、验证继电保护装置的动作逻辑灵敏性,并为系统控制策略优化及故障诊断提供理论支撑和技术依据。; 适合人群:电气工程及其自动化、电力系统及其相关专业的高校本科生、研究生、科研人员,以及从事电力系统仿真分析、继电保护设计、电网运行维护等工作的工程技术人员。; 使用场景及目标:①用于高校教学科学研究中对发电机故障机理及暂态过程的可视化分析深入探讨;②支撑电力系统安全稳定分析、保护定值整定计算、控制策略优化应急预案制定;③为实际电网故障后的诊断溯源、事故回溯应急处置决策提供可靠的仿真平台理论指导。; 阅读建议:建议读者结合MATLAB/Simulink仿真环境进行实践操作,按照文档指导逐步搭建仿真模型,设置不同类型的故障条件进行对比实验,重点观察并分析电压、电流波形的幅值、相位及衰减特性,深入理解其物理成因系统影响,有条件者可进一步将模型扩展至多机系统以提升研究的工程应用价值。
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 在信息技术行业,特别是智能手机维修和改进的范畴内,“高通9008免拆机救黑砖教程工具”被视为一种通用的处理手段,它主要服务于那些面对设备无法正常运作或处于“黑砖”状态的消费者。这个压缩文件内含针对搭载高通处理器的智能手机的救援指南实用工具,其核心目标在于协助用户在不进行物理拆解的前提下,成功进入9008模式,进而完成对手机的修复。 我们必须明确理解“高通9008模式”的概念。9008代表了高通芯片的一种下载状态,也称作EDL(eMMC Download Mode)。在该状态下,用户或技术人员能够直接对手机的存储单元进行编程操作、系统升级或固件回载,以此应对软件层面的故障。此类模式一般应用于手机无法正常启动或遭遇严重故障的场合,属于一种较为根本性的修复措施。 “黑砖”状态描述了手机因软件层面的异常而无法开机或完全失去反应的情况,其成因通常涉及系统崩溃、刷机失败、恶意软件入侵等。当常规的恢复措施如强制重启、恢复界面等手段均告无效时,就需要借助9008模式这类特殊通道来实施修复。 小米品牌手机广泛采用了高通处理器,因此当其产品遭遇黑砖问题时,该教程工具显示出极大的实用价值。此压缩文件可能包含以下组成部分: 1. **救砖教程**:提供详尽的流程说明,引导用户如何安全地将设备导入9008模式,以及如何运用相关工具执行固件恢复或刷新操作。 2. **驱动程序**:高通9008模式的有效运行依赖于特定的驱动程序以实现电脑的通信,压缩包中或许就整合了这些驱动,用户需先行安装它们以便连接手机并开展修复工作。 3. **线刷工具**:诸如MiFlash、QFIL等工具,它们能够支持用户通过...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值