如何在点击儿童时只触发父级点击事件 [英] How to ONLY trigger parent click event when a child is clicked

查看:105
本文介绍了如何在点击儿童时只触发父级点击事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

孩子和父母都是可点击的(孩子可能是带有jQuery点击事件的链接或div)。当我点击孩子时,我该如何触发父级点击事件而不是子级事件?

DOM Event Phase h2>

活动分为三个阶段:


  1. 拍摄:第一阶段是捕获,其中事件处理程序从< window> 开始调用,并通过后代向下移动到事件目标。

  2. 目标:第二阶段是调用目标上的事件侦听器时的目标阶段。
  3. 冒泡:第三阶段是冒泡,首先处理程序首先调用目标的父对象,然后渐进地,元素。

事件也有一个默认操作,它在冒泡阶段之后发生。默认操作是浏览器定义的操作,通常针对作为事件目标的元素种类上指定类型的事件发生(例如浏览器导航到 href < a> 点击后显示,而点击 $ b> b



图片版权所有©2016 万维网联盟,( MIT ERCIM Keio ,< a href =http://ev.buaa.edu.cn/ =noreferrer>北航)。 http://www.w3.org/Consortium/Legal/2015/doc-license (根据许可证允许使用)



有关捕获和冒泡的更多信息,请参阅:什么是事件冒泡和捕获?; DOM 3级事件草案;或者 W3C DOM4:Events



< h1>阻止事件发生给孩子

为了您想要的事情,要在事件发生之前将事件发送给父母,并防止事件发生在孩子身上,必须在捕获阶段接收事件。一旦在捕获阶段收到它,您必须停止事件传播到DOM树中较低元素的任何事件处理程序,或者已经注册在冒泡阶段侦听的所有事件处理程序(即,所有侦听器在元素/阶段在你的听众之后被事件访问)。您可以通过致电 event.stopPropagation( )



在拍摄阶段接收事件



当使用 addEventListener(type,listener)添加侦听器[,useCapture]) ,您可以将 useCapture 参数设为 true



引用MDN:


[ useCapture is]一个布尔值,指示此类型的事件将在调度到DOM树下的任何EventTarget之前分派给注册的侦听器。在树中冒泡的事件不会触发指定使用捕获的侦听器。当两个元素都注册了该事件的句柄时,事件冒泡和捕获是传播嵌套在另一个元素中的元素中发生的事件的两种方式。事件传播模式确定元素接收事件的顺序。有关详细说明,请参阅DOM Level 3事件和JavaScript事件顺序。如果未指定, useCapture 默认为false。




防止其他处理程序获取事件





示例



在以下示例中,事件侦听器位于父和< div> 元素的子元素。只有放在父级上的侦听器才会收到该事件,因为它在子级之前的捕获阶段接收到该事件,并执行 event.stopPropagation()



child'); var preventChild = document.getElementById('preventChild'); parent.addEventListener('click',function(event){if(preventChild.checked){event.stopPropagation();} event.preventDefault(); var targetText; if(event.target === parent){targetText ='parent';} if(event.target === child){targetText ='child';} console.log('Click Detected in parent on'+ targetText);},TRUE); child.addEventListener('click',function(event){console.log('Click Detected in child(bubbling phase)');}); child.addEventListener('click',function(event){console.log('单击在子级中检测到(捕获阶段)');},true);

 < input id =preventChildtype =checkboxchecked>阻止儿童获取事件< / input>< div id =parent>父文字< br /> < div id =childstyle =margin-left:10px;>儿童文字< br /> < / div>< / div>  

h2>

jQuery不支持在事件上使用捕获。有关原因的详细信息,请参阅:为什么jQuery事件模型不支持事件捕获并仅支持事件冒泡


Both child and parent are clickable (child could be a link or div with jQuery click events). When I click on child, how do I only trigger parent click event but not the child event?

解决方案

DOM Event Phases

Events have three phases:

  1. Capture: The first phase is "capture" where event handlers are called starting with the <window> and moving down through descendants towards the target of the event.
  2. Target: The second phase is the "target" phase when the event listeners on the target are called.
  3. Bubbling: The third phase is "bubbling" which starts with the handlers listening on parent of the target being called first, then, progressively, the ancestors of that element.

Events also have a "default action", which happens after the bubbling phase. The default action is the browser-defined action that normally occurs for events of the specified type on the kind of element which is the target of the event (e.g. the browser navigating to the href of an <a> upon a click, whereas a click on another type of element will have a different default action).

The DOM Level 3 Events draft has a diagram that graphically shows how events propagate through the DOM:


Image Copyright © 2016 World Wide Web Consortium, (MIT, ERCIM, Keio, Beihang). http://www.w3.org/Consortium/Legal/2015/doc-license (Use permitted per the license)

For more information, on capture and bubbling, see: "What is event bubbling and capturing?"; The DOM Level 3 Events draft; or W3C DOM4: Events

Preventing the event from getting to the child

For what you want, to get the event on the parent prior to, and prevent, the event on the child, you have to receive the event in the capture phase. Once you have received it in the capture phase, you have to stop the event from propagating to any event handlers on elements lower in the DOM tree, or which have registered to listen in the bubbling phase (i.e. all listeners on elements/phases which would be visited by the event after your listener). You do this by calling event.stopPropagation().

Receiving events during the capture phase

When adding the listener with addEventListener(type, listener[, useCapture]), you can have the useCapture argument be true.

Quoting MDN:

[useCapture is] A Boolean that indicates that events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree. Events that are bubbling upward through the tree will not trigger a listener designated to use capture. Event bubbling and capturing are two ways of propagating events that occur in an element that is nested within another element, when both elements have registered a handle for that event. The event propagation mode determines the order in which elements receive the event. See DOM Level 3 Events and JavaScript Event order for a detailed explanation. If not specified, useCapture defaults to false.

Preventing other handlers getting the event

  • event.preventDefault() is used to prevent the default action (e.g. prevent the browser from navigating to the href of an <a> upon a click). [This is used in the example below, but has no real effect as there is no default action for text. It's used here because most of the time when you are adding a click event handler you want to prevent the default action. Thus, it's a good idea to be in the habit of doing so, and just not doing so when you know you don't want to.]
  • event.stopPropagation() is used to prevent any handlers on elements later in any of the event phases from receiving the event. It does not prevent any additional handlers on the current element and phase from being called. It does not prevent the default action from occurring.
  • event.stopImmediatePropagation(): Handlers on the same element and phase are called in the order in which they are added. In addition to having the same effect as event.stopPropagation(), event.stopImmediatePropagation() prevents any additional handlers on the same element and event phase from receiving the event. It does not prevent the default action from occurring. Given that the requirement for this question is to prevent the event from propagating to children, we don't need to use this, but could do so instead of using event.stopPropagation(). Note, however, that listeners on the same element are called in the order they are added. Thus, event.stopImmediatePropagation() will not prevent the event from being received by those listeners on the same element and phase as your listener which were added prior to your listener.

Example

In the following example, event listeners are placed on both the parent and the child <div> elements. Only the listener placed on the parent receives the event because it receives the event during the capture phase prior to the child and it executes event.stopPropagation().

var parent=document.getElementById('parent');
var child=document.getElementById('child');
var preventChild=document.getElementById('preventChild');

parent.addEventListener('click',function(event){
    if(preventChild.checked) {
        event.stopPropagation();
    }
    event.preventDefault();
    var targetText;
    if(event.target === parent) {
        targetText='parent';
    }
    if(event.target === child) {
        targetText='child';
    }
    console.log('Click Detected in parent on ' + targetText);
},true);
                      
child.addEventListener('click',function(event){
    console.log('Click Detected in child (bubbling phase)');
});

child.addEventListener('click',function(event){
    console.log('Click Detected in child (capture phase)');
},true);

<input id="preventChild" type="checkbox" checked>Prevent child from getting event</input>
<div id="parent">Parent Text<br/>
  <div id="child" style="margin-left:10px;">Child Text<br/>
  </div>
</div>

jQuery

jQuery does not support using capture on events. For more information as to why see: "Why does jQuery event model does not support event Capture and just supports event bubbling"

这篇关于如何在点击儿童时只触发父级点击事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆