이 글은 주로 Javascript 이벤트 버블링 메커니즘의 세부 소개에 대한 관련 정보를 소개합니다. 필요한 친구는 이를 참조할 수 있습니다.
1. 이벤트
브라우저 클라이언트 애플리케이션 플랫폼에서는 기본적으로 모든 것이 이벤트 중심입니다. , 이벤트가 발생하고 그에 따른 조치가 취해집니다.
브라우저 이벤트는 어떤 일이 발생했다는 신호를 나타냅니다. 이벤트를 자세히 설명하는 것은 이 기사의 초점이 아닙니다. 아직 이해하지 못한 친구들은 W3school 튜토리얼을 방문하여 다음 내용을 더 잘 이해하는 데 도움이 될 것입니다.
2. 버블 메커니즘
버블링이란?
아래 그림을 이해하셔야 합니다. 거품은 물 밑바닥에서 시작하여 깊은 곳에서 얕은 곳으로, 위로 올라갑니다. 올라가는 동안 거품은 다양한 깊이의 물을 통과합니다.
이 버블은 여기서의 이벤트와 동일하며 물은 전체 DOM 트리와 동일합니다. 이벤트는 DOM 트리의 루트 노드로 전달될 때까지 전달됩니다. 돔.
간단한 사례 분석
다음은 버블링 원리를 설명하는 간단한 예입니다. 세 가지 간단한 dom 요소로 html을 정의합니다: p1, p2,span, p2 포함 범위, p1 포함 p2 ;<body id="body"> <p id="box1" class="box1"> <p id="box2" class="box2"> <span id="span">This is a span.</span> </p> </p> </body>
<script type="text/javascript"> window.onload = function() { document.getElementById("body").addEventListener("click",eventHandler); } function eventHandler(event) { console.log("时间:"+new Date(event.timeStamp)+" 产生事件的节点:" + event.target.id +" 当前节点:"+event.currentTarget.id); } </script>
전체 HTML 코드는 다음과 같습니다:
Insert title here <script type="text/javascript"> window.onload = function() { document.getElementById("body").addEventListener("click",eventHandler); } function eventHandler(event) { console.log("时间:"+new Date(event.timeStamp)+" 产生事件的节点:" + event.target.id +" 当前节点:"+event.currentTarget.id); } </script> <body id="body"> <p id="box1" class="box1"> <p id="box2" class="box2"> <span id="span">This is a span.</span> </p> </p> </body>
b. 이벤트 버블링을 종료합니다.
이제 p1이 다음과 같은 경우 이러한 함수를 구현하려고 합니다. p2를 클릭하면 "안녕하세요, 저는 두번째 레이어입니다."라는 팝업이 뜹니다. 여기에서 다음과 같은 자바스크립트 조각이 생성됩니다:<script type="text/javascript"> window.onload = function() { document.getElementById("box1").addEventListener("click",function(event){ alert("您好,我是最外层p。"); }); document.getElementById("box2").addEventListener("click",function(event){ alert("您好,我是第二层p。"); }); document.getElementById("span").addEventListener("click",function(event){ alert("您好,我是span。"); }); } </script>
这显然不是我们想要的! 我们希望的是点谁显示谁的信息而已。为什么会出现上述的情况呢? 原因就在于事件的冒泡,点击span的时候,span 会把产生的事件往上冒泡,作为父节点的p2 和 祖父节点的p1也会收到此事件,于是会做出事件响应,执行响应函数。现在问题是发现了,但是怎么解决呢?
方法一:我们来考虑一个形象一点的情况:水中的一个气泡正在从底部往上冒,而你现在在水中,不想让这个气泡往上冒,怎么办呢?——把它扎破!没了气泡,自然不会往上冒了。类似地,对某一个节点而言,如果不想它现在处理的事件继续往上冒泡的话,我们可以终止冒泡:
在相应的处理函数内,加入 event.stopPropagation() ,终止事件的广播分发,这样事件停留在本节点,不会再往外传播了。修改上述的script片段:
<script type="text/javascript"> window.onload = function() { document.getElementById("box1").addEventListener("click",function(event){ alert("您好,我是最外层p。"); event.stopPropagation(); }); document.getElementById("box2").addEventListener("click",function(event){ alert("您好,我是第二层p。"); event.stopPropagation(); }); document.getElementById("span").addEventListener("click",function(event){ alert("您好,我是span。"); event.stopPropagation(); }); } </script>
经过这样一段代码,点击不同元素会有不同的提示,不会出现弹出多个框的情况了。
方法二:事件包含最初触发事件的节点引用 和 当前处理事件节点的引用,那如果节点只处理自己触发的事件即可,不是自己产生的事件不处理。event.target 引用了产生此event对象的dom 节点,而event.currrentTarget 则引用了当前处理节点,我们可以通过这 两个target 是否相等。
比如span 点击事件,产生一个event 事件对象,event.target 指向了span元素,span处理此事件时,event.currentTarget 指向的也是span元素,这时判断两者相等,则执行相应的处理函数。而事件传递给 p2 的时候,event.currentTarget变成 p2,这时候判断二者不相等,即事件不是p2 本身产生的,就不作响应处理逻辑。
<script type="text/javascript"> window.onload = function() { document.getElementById("box1").addEventListener("click",function(event){ if(event.target == event.currentTarget) { alert("您好,我是最外层p。"); } }); document.getElementById("box2").addEventListener("click",function(event){ if(event.target == event.currentTarget) { alert("您好,我是第二层p。"); } }); document.getElementById("span").addEventListener("click",function(event){ if(event.target == event.currentTarget) { alert("您好,我是span。"); } }); } </script>
比较:
从事件传递上看:方法一在于取消事件冒泡,即当某些节点取消冒泡后,事件不会再传递;方法二在于不阻止冒泡,过滤需要处理的事件,事件处理后还会继续传递;
优缺点:
方法一缺点:为了实现点击特定的元素显示对应的信息,方法一要求每个元素的子元素也必须终止事件的冒泡传递,即跟别的元素功能上强关联,这样的方法会很脆弱。比如,如果span 元素的处理函数没有执行冒泡终止,则事件会传到p2 上,这样会造成p2 的提示信息;
方法二缺点:方法二为每一个元素都增加了事件监听处理函数,事件的处理逻辑都很相似,即都有判断 if(event.target == event.currentTarget),这样存在了很大的代码冗余,现在是三个元素还好,当有10几个,上百个又该怎么办呢?
还有就是为每一个元素都有处理函数,在一定程度上增加逻辑和代码的复杂度。
我们再来分析一下方法二:方法二的原理是 元素收到事件后,判断事件是否符合要求,然后做相应的处理,然后事件继续冒泡往上传递; 既然事件是冒泡传递的,那可不可以让某个父节点统一处理事件,通过判断事件的发生地(即事件产生的节点),然后做出相应的处理呢?答案是可以的,下面通过给body 元素添加事件监听,然后通过判断event.target 然后对不同的target产生不同的行为。
将方法二的代码重构一下:
<script type="text/javascript"> window.onload = function() { document.getElementById("body").addEventListener("click",eventPerformed); } function eventPerformed(event) { var target = event.target; switch (target.id) { case "span": alert("您好,我是span。"); break; case "p1": alert("您好,我是第二层p。"); break; case "p2": alert("您好,我是最外层p。"); break; } } </script>
结果会是点击不同的元素,只弹出相符合的提示,不会有多余的提示。
위의 방법을 통해 각 요소가 완료해야 하는 처리 기능을 상위 노드 본문 요소에 넘겨주었습니다. 즉, 응답 논리를 본문에 위임합니다. 이 모델은 소위 이벤트 위임입니다.
다음은 개략도입니다.
위는 모든 사람을 위해 정리한 내용입니다. 앞으로 모든 사람에게 도움이 되기를 바랍니다.
관련 기사:
JavaScript 쿠키에 대한 자세한 설명 및 간단한 예제 응용 프로그램(그림 및 텍스트 자습서)
기본적이고 강력한 DOM 선택기 querySelector에 대한 자세한 소개(코드 첨부)
여러 유형의 javascript 댓글 코드 방법(그림 및 텍스트 튜토리얼)
위 내용은 Javascript 이벤트 버블링 메커니즘에 대한 자세한 소개(그래픽 튜토리얼)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!