手机版

Javascript事件冒泡机制的详细介绍

时间:2021-09-07 来源:互联网 编辑:宝哥软件园 浏览:

1.事件

在浏览器客户端应用平台中,基础学生都是事件驱动的,即当一个事件发生时,做出相应的动作。

浏览器事件是某些事情发生的信号。事件的解释不是本文的重点。对于还不了解的人,可以访问W3school教程了解一下,这将有助于你更好地理解以下内容。

2.气泡机制

什么是冒泡?

你应该理解下图。气泡从水底升起,从深到浅,到顶部。在上升的过程中,气泡会通过不同深度的水。

相应的:这个泡泡相当于我们这里的事件,而水相当于我们整个dom树;事件从dom树的底层传递到dom的根节点。

简单案例分析

这里有一个简单的例子来说明冒泡原理:

用三个简单的dom元素定义一个html:div1,div2,span,div2包含span,div 1包含div 2;它们都在身体下面:

body id=' body ' div id=' box1 ' class=' box1 ' div id=' box2 ' class=' box2 ' span id=' span '这是一个span。/span/div/div/body接口原型如下:

在此基础上,我们实现了以下功能:

A.body添加了click事件监视,当body捕获事件时,它会打印出事件的时间和触发事件的节点信息:

脚本类型=' text/JavaScript ' window . onload=function(){ document . getelementbyid(' body ')。addEventListener('click ',eventHandler);}函数event handler(event){ console . log(' time:' new Date(event . timestamp)'生成事件的节点:' event.target.id '当前节点:' event . current target . id);}/script当我们依次点击‘这是span’、div2、div1和body时,会输出以下信息:

分析以上结果:

无论是body,body的子元素div1,div的子元素div2,还是span,当点击这些元素时,都会产生一个click事件,并捕获body,然后调用相应的事件处理程序。就像水中的气泡从底部上升到顶部一样,事件也会过去。

事件传输示意图如下:

一般来说,事件的传输过程中会有一些信息,这些信息是事件的组成部分:事件发生的时间、事件发生的地点、事件的类型、事件的当前处理程序、其他信息,

完整的html代码如下:

!DOCTYPE html htmlheartheta charset=' UTF-8 '脚本类型=' text/JavaScript ' src=' http : js/jquery-1 . 11 . 0 . js '/script title在此插入标题/title style type=' text/CSS ' . box 1 { border : green 40px solid;宽度: 300 px;height: 300pxmargin: auto}.box2 { border:黄色40px固体;宽度: 220 px;高度: 220 px;margin: auto} span { position: relativeleft: 50pxtop: 50px背景-color: rgba(128,128,128,0.22);}/style script type=' text/JavaScript ' window . onload=function(){ document . getelementbyid(' body ')。addEventListener('click ',eventHandler);}函数event handler(event){ console . log(' time:' new Date(event . timestamp)'生成事件的节点:' event.target.id '当前节点:' event . current target . id);}/script/head body id=' body ' div id=' box1 ' class=' box1 ' div id=' box2 ' class=' box2 ' span id=' span '这是一个span。停止事件的冒泡

我们现在就想实现这个功能。点击div1,弹出‘你好,我是最外面的div’。当你点击div2时,弹出‘你好,我是第二个div’;当您单击span时,“你好,我是span。”。

所以我们有下面的javascript片段:

脚本类型=' text/JavaScript ' window . onload=function(){ document . getelementbyid(' box 1 ')。addeventlistener ('click '),function (event) {alert ('hello,我是最外面的div . ');});文件。getelementbyid ('box2 ')。addeventlistener ('click '),function (event) {alert ('hello,这是第二个div。);});Document.getelementbyid ('span ')。addeventlistener ('click '),function (event) {alert ('hello,这是span . ');});}/script期望当上面的代码点击span时,会弹出一个对话框‘你好,这里是span。’是的,此对话框确实会弹出:

但是,单击“确定”后,不仅会生成此对话框,还会依次弹出以下对话框:

这显然不是我们想要的!我们想要的是展示谁的信息。为什么会这样?原因在于事件的冒泡。当您单击span时,span将弹出生成的事件。div2(父节点)和div1(祖父节点)也将接收此事件,因此它们将做出事件响应并执行响应函数。现在问题找到了,但是怎么解决呢?

方法一:我们来考虑一个更生动的情况:水中的一个气泡从底部升起,但你现在在水中,你不想让这个气泡升起。你该怎么办?——刺穿它!没有泡沫,自然不会涨。同样,对于某个节点,如果我们不希望它正在处理的事件继续向上冒泡,我们可以停止冒泡:

在相应的处理函数中,添加event.stopPropagation()终止事件的广播分发,使事件停留在此节点,不会扩散出去。修改上面的脚本片段:

脚本类型=' text/JavaScript ' window . onload=function(){ document . getelementbyid(' box 1 ')。addeventlistener ('click '),function (event) {alert ('hello,我是最外面的div . ');event . stopperpagation();});文件。getelementbyid ('box2 ')。addeventlistener ('click '),function (event) {alert ('hello,这是第二个div。);event . stopperpagation();});Document.getelementbyid ('span ')。addeventlistener ('click '),function (event) {alert ('hello,这是span . ');event . stopperpagation();});}/script在这样一段代码之后,点击不同的元素会给你不同的提示,并且不会弹出多个框。

方法2:事件包含最初触发事件的节点的引用和当前处理事件的节点的引用。如果节点只处理它自己触发的事件,它将不会处理不是它自己生成的事件。Event.target指生成此事件对象的dom节点,event.currrentTarget指当前处理节点。我们可以检查这两个目标是否相等。

例如,当span单击一个事件时,会生成一个事件对象,event.target指向span元素。当span处理此事件时,event.currentTarget也指向span元素。如果判断它们相等,将执行相应的处理功能。当事件传递到div2时,event.currentTarget变成div2。此时,如果判断该事件不是由div2本身产生的,则不进行响应处理逻辑。

脚本类型=' text/JavaScript ' window . onload=function(){ document . getelementbyid(' box 1 ')。addeventlistener ('click '),function(event){ if(event . target==event . current target){ alert(' hello,我是最外面的div . ');} });文件。getelementbyid ('box2 ')。addeventlistener ('click ',function (event) {if (event。target==事件。currenttarget) {alert ('hello,这是第二个div。);} });Document.getelementbyid ('span ')。addeventlistener ('click ',function (event) {if (event。target==事件。currenttarget) {alert('你好,我是span。);} });}/脚本比较:

从事件传输的角度来看,第一种方法是取消事件冒泡,即当部分节点取消冒泡时,事件不会再次传输;第二种方法是不防止冒泡,过滤需要处理的事件,事件处理完毕后继续通过;

优点和缺点:

方法1的缺点:为了点击一个特定的元素来显示相应的信息,方法1要求每个元素的子元素也必须终止事件的冒泡传输,即它们在功能上与其他元素强相关,所以这种方法会非常脆弱。比如span元素的处理功能不执行气泡终止,事件会传到div2,会引起div2的提示信息;

方法2的缺点:在方法2中,每个元素都添加了一个事件监控和处理功能,事件的处理逻辑非常相似,即有一个判断if (event。target==事件。currenttarget),这导致了很大的代码冗余。现在,三个要素都可以。10个以上,上百个的时候怎么办?每个元素还有一个处理函数,在一定程度上增加了逻辑和代码的复杂度。

我们再来分析一下方法2:方法2的原理是元素收到事件后,判断事件是否符合要求,然后进行相应的处理,然后事件继续冒泡;由于事件是在气泡中传输的,父节点能否统一处理事件,通过判断事件发生的位置(即事件发生的节点),然后进行相应的处理?答案是肯定的。接下来,通过向body元素添加事件监视,然后判断event.target,为不同的目标生成不同的行为。

重构方法2的代码:

脚本类型=' text/JavaScript ' window . onload=function(){ document . getelementbyid(' body ')。addEventListener('click ',event performed);}函数event performed(event){ var target=event . target;switch(target . id){ case ' span ' : alert(' Hello,我是span . ');打破;案例“div 1”:警报(“你好,这是二级div。”);打破;案例“div 2”:警报(“你好,我是最外面的div。”);打破;} }/script导致点击不同的元素,只会弹出匹配的提示,没有多余的提示。

通过以上方式,我们已经将每个元素应该具有的处理功能交给了它的祖父节点,body元素。也就是说,span、div2、div1把自己的响应逻辑委托给身体,让它完成相应的逻辑,而不实现相应的逻辑。这种模式称为事件委托。

以下是示意图:

关于活动代理的问题,我们以后会继续讨论。

感谢您的阅读,希望对大家有所帮助,感谢您对本网站的支持!

版权声明:Javascript事件冒泡机制的详细介绍是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。