Javascript DOM事件流的理解 - 极悦
专注Java教育14年 全国咨询/投诉热线:444-1124-454
极悦LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 Javascript DOM事件流的理解

Javascript DOM事件流的理解

更新时间:2022-10-31 09:30:57 来源:极悦 浏览844次

一个事件的生命周期分为三个阶段:捕获、目标和冒泡。

捕获阶段

当一个事件被触发时,浏览器会识别出与该事件相关的元素,该元素被称为事件的目标。

浏览器识别 body 元素和 target 之间的所有元素,并检查每个元素以查看它们是否有任何事件处理程序要求通知其后代的事件。

浏览器在触发目标本身的处理程序之前触发任何此类处理程序。

下面是代码。

让香蕉=文档.getElementById(“香蕉”);
让textblock = document .getElementById( "block1" );
香蕉.addEventListener(“鼠标悬停”,handleMouseEvent);
香蕉.addEventListener( "mouseout" ,handleMouseEvent);
textblock.addEventListener( "mouseover" , handleDescendantEvent, true);
textblock.addEventListener( "mouseout" , handleDescendantEvent, true);
函数handleDescendantEvent(e) {
   if (e.type == "mouseover" && e.eventPhase == Event.CAPTURING_PHASE) {
        e.target.style.border = "厚实红色" ;
        e.currentTarget.style.border = "厚双黑" ;
  } else if (e.type == "mouseout" && e.eventPhase == Event.CAPTURING_PHASE) {
        e.target.style.removeProperty( "border" );
        e.currentTarget.style.removeProperty( "border" );
  } / * w w w 。d e m o 2秒。厘米* / _ _                            
}
函数handleMouseEvent(e) {
     if (e.type == "mouseover" ) {
        e.target.style.background= '白色' ;
        e.target.style.color= '黑色' ;
    } 别的 {
        e.target.style.removeProperty( 'color' );
        e.target.style.removeProperty( '背景' );
    }
}
< ! DOCTYPE HTML > < html > < head > < style type= "text/css" > p { < ! - - w w w 。d e m o 2秒。c o m - - >背景:灰色;
                颜色:白色;
                填充:10px;
                边距:5px;
                边框:细实黑色                                                        
            }
            跨度{
                背景:白色;
                颜色:黑色;
                填充:2px;
                光标:默认;
            }
        </style> 
    </head> 
    < body > 
        < p  id = "block1" > 
            test < span  id = "banana" >香蕉</span> test
         </p>
        <脚本类型= “文本/javascript” >
            让香蕉=文档.getElementById(“香蕉”);
            让 textblock = document .getElementById( "block1" );
            香蕉.addEventListener(“鼠标悬停”,handleMouseEvent);
            香蕉.addEventListener( "mouseout" ,handleMouseEvent);
            textblock.addEventListener( "鼠标悬停" ,
                          处理后代事件,真);
            textblock.addEventListener( "mouseout" ,
                          处理后代事件,真);
            函数句柄后代事件(e){
              if (e.type == "鼠标悬停" &&
                        e.eventPhase == Event.CAPTURING_PHASE) {
                    e.目标。风格。边框= “厚实的红色”;
                    e.当前目标。风格。边框= “厚双黑”;
              } else if (e.type == "mouseout" &&
                        e.eventPhase == Event.CAPTURING_PHASE) {
                    e.目标。样式.removeProperty( "边框" );
                    e.当前目标。样式.removeProperty( "边框" );
              }
            }
            函数句柄鼠标事件(e){
                如果(e.type == “鼠标悬停”){
                    e.目标。风格。背景= '白色' ;
                    e.目标。风格。颜色= '黑色' ;
                } 别的 {
                    e.目标。样式.removeProperty( 'color' );
                    e.目标。样式.removeProperty( '背景' );
                }
            }
        </script> 
    </body> 
</html>

在这个例子中,我们定义了一个<span>元素作为 p 元素的子元素,并为mouseover和mouseout事件注册了处理程序。

请注意,当我们向父元素(p 元素)注册时,我们向addEventListener () 方法添加了第三个参数,如下所示:

textblock.addEventListener( "mouseover" , handleDescendantEvent, true);

这个附加参数告诉浏览器我们希望<p>元素在捕获阶段接收其后代元素的事件。

当 mouseover 事件被触发时,浏览器从 HTML 文档的根开始,并开始沿着 DOM 向下移动到目标,即触发事件的元素。

对于层次结构中的每个元素,浏览器都会检查它是否已经注册了对捕获事件的兴趣。

在每个元素处,浏览器都会调用任何启用了捕获的侦听器。

在这种情况下,浏览器会找到并调用我们在<p>元素中注册 的handleDescendantEvent () 函数。

当调用handleDescendantEvent () 函数时,Event对象通过target 属性包含有关目标元素的信息,以及通过 currentTarget属性导致调用该函数的元素的信息。

我们使用这两个属性,以便我们可以更改 p 元素和 span 子元素的样式。

事件捕获使每个元素的祖先有机会在将事件传递给元素本身之前对其做出反应。

父元素事件处理程序可以通过在 Event 对象上调用stopPropagation () 或stopImmediatePropagation () 函数来停止事件向下流向目标。

stopPropagation () 将确保为当前元素注册的所有事件侦听器都将被调用,而stopImmediatePropagation () 将忽略任何未触发的侦听器。

以下代码显示了将 stopPropagation 函数添加到 handleDescendantEvent () 事件处理程序。

防止进一步的事件流。

...
函数handleDescendantEvent(e) {
     if (e.type == "mouseover" && e.eventPhase == Event.CAPTURING_PHASE) {
        e.target.style.border = "厚实红色" ;
        e.currentTarget.style.border = "厚双黑" ;
    } else if (e.type == "mouseout" && e.eventPhase == Event.CAPTURING_PHASE) {
        e.target.style.removeProperty( "border" );
        e.currentTarget.style.removeProperty( "border" );
    }
    e.stopPropagation();
}
 ...
< ! DOCTYPE HTML > < html > < head > < style type= "text/css" > p { < ! - - w w w 。d e m o 2秒。c o m - - >背景:灰色;
                颜色:白色;
                填充:10px;
                边距:5px;
                边框:细实黑色                                                        
            }
            跨度{
                背景:白色;
                颜色:黑色;
                填充:2px;
                光标:默认;
            }
        </style> 
    </head> 
    < body > 
        < p  id = "block1" > 
            test < span  id = "banana" >香蕉</span> test
         </p>
        <脚本类型= “文本/javascript” >
            让香蕉=文档.getElementById(“香蕉”);
            让 textblock = document .getElementById( "block1" );
            香蕉.addEventListener(“鼠标悬停”,handleMouseEvent);
            香蕉.addEventListener( "mouseout" ,handleMouseEvent);
            textblock.addEventListener( "鼠标悬停" ,
                                处理后代事件,真);
            textblock.addEventListener( "mouseout" ,
                                处理后代事件,真);
            函数句柄后代事件(e){
                if (e.type == "鼠标悬停" &&
                         e.eventPhase == Event.CAPTURING_PHASE) {
                    e.目标。风格。边框= “厚实的红色”;
                    e.当前目标。风格。边框= “厚双黑”;
                } else if (e.type == "mouseout" &&
                         e.eventPhase == Event.CAPTURING_PHASE) {
                    e.目标。样式.removeProperty( "边框" );
                    e.当前目标。样式.removeProperty( "边框" );
                }
                e.stopPropagation();
            }
            函数句柄鼠标事件(e){
                如果(e.type == “鼠标悬停”){
                    e.目标。风格。背景= '白色' ;
                    e.目标。风格。颜色= '黑色' ;
                } 别的 {
                    e.目标。样式.removeProperty( 'color' );
                    e.目标。样式.removeProperty( '背景' );
                }
            }
        </script> 
    </body> 
</html>

通过此更改,浏览器捕获阶段在调用 p 元素上的处理程序时结束。

不会检查其他元素,并且将跳过目标和冒泡阶段。

就示例而言,这意味着将不会应用 handleMouseEvent () 函数中的样式更改以响应鼠标悬停事件。

请注意,在处理程序中,我们检查事件类型并使用 eventPhase 属性确定事件处于哪个阶段,如下所示:

...
 if (e.type == "mouseover" && e.eventPhase == Event.CAPTURING_PHASE) {
...

在注册事件侦听器时启用捕获事件不会停止针对元素本身的事件。

在这种情况下,p 元素会占用浏览器屏幕上的空间,并且也会响应 mouseover 事件。

为避免这种情况,我们检查以确保仅在处理处于捕获阶段的事件时应用样式更改。

以后代元素为目标的事件,我们只处理这些事件,因为我们已经注册了一个启用捕获的侦听器。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>