ChatGPT解决这个技术问题 Extra ChatGPT

如何仅在单击子项时触发父单击事件

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?

Why would you have an event on the child, if it's never suppose to trigger?
You can bind the children's click events to the parent element.
Please consider including an example of your context to help demonstrate what you want to achieve.
@LinusAronsson makes a good point. You'll want to look at event bubbling. This way child events can react to the click, but by returning false bubble the event up to the parent so it can handle it as needed as well. I would recommend you also include more information as showdev mentioned as without concrete examples it's hard to see how this may need to function.

C
Community

DOM Event Phases

Events have three phases:

Capture: The first phase is "capture" where event handlers are called starting with the and moving down through descendants towards the target of the event. Target: The second phase is the "target" phase when the event listeners on the target are called. 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:

https://i.stack.imgur.com/rUhpq.png

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 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); Prevent child from getting event

Parent Text
Child Text

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"


This is a great answer. The OP of the question might want to read it and accept.
How do you use the capture for IE element['onclick'] = function(e) {}; ?
A
Abraham Brookes

Another option for this that may be useful in certain circumstances when you know that none of the child elements are interactive is to set pointer-events: none in your css (link). I usually apply it to all child elements of the element on which I want to capture interaction. Like this:

#parentDiv * {
    pointer-events: none
}

Note the *, declaring that the rule applies to all children of the parentDiv.


Interesting solution (+1). It does, however, have the drawback of preventing all other types of pointer events, not just clicks, from reaching the children.
This solution was simple and suited my needs perfectly, thanks for solving a problem I was having.
Any idea if this will work on mobile touch events?
@AnandRockzz I'm pretty sure it does, I have used it in mobile production, and on mobile the touch is considered a 'pointer'
Awesome, perfectly for my case.
y
yaya

Prevent the children from receiving the parent's click event:

parent.addEventListener('click',function(e){
  e.stopPropagation();
  console.log('event on parent!')
},true);

(Note that the second parameter is true)

Prevent the parent from receiving itself or it children's click event:

parent.addEventListener('click',function(e){
  e.stopPropagation();
  console.log('event on parent or childs!', e.target.closest('.parent_selector'))
});

e.stopPropagation means that stop next ones in the hierarchy to receive the event.

second argument (useCapture) is a flag, and means that reverse the order of receiving events. (use capture phase instead of bubble phase.). it means if you set it to true, parent will receive the click event, then the child. (normally the child will get the event first.)

(see the @Makyen's answer for detailed explanation.)


V
Vinod Kumar

To make life really simple and easy here i am Use on parent node similar to this

target_image.addEventListener('drop',dropimage,true);

This will enable the parent child ancestor relationship and the same event will be called in for the parent and child. To make the event only be called for the parent use the following code snippet in the event handler. First line

event.stopPropagation();
event.preventDefault();

S
Sachithra Pathiraja

You can use $event.stopPropagation() in the html file.

(click)="openAttendeesList(event.id,event.eventDetailId,event.eventDate) ; $event.stopPropagation();"


r
repzero

You can use the CustomEvents property on elements.

Create an event object and let the child element dispatch the event to its parent

see demo here

document.getElementById('parent').onclick = function() { alert("you are clicking on the parent stop it"); } document.getElementById('child').onclick = function(e) { alert('I am sending this event to my parent'); event = new CustomEvent('click'); document.getElementById('parent').dispatchEvent(event); } #parent { display: inline-block; width: 100px; height: 100px; border: solid black; } #child { border: solid red; }

I am a child


The question specifically asks about "only trigger parent click event but not the child event". The way that you have done this, the event on the child is still fired (and any other listeners are also called).
Further, unless you completely control both the HTML and all JavaScript for the page, using the element.onclick property is a bad idea. Assigning to that property supplants any listener already defined that way (only one can exist on the property/attribute). That can cause pages which you do not completely control to break. In JavaScript, it is much better to use addEventListener().
agree with your second comment but not your first....the title of the OP question states "How to ONLY trigger parent click event when a child is clicked"..The user clicks on the child which trigger the parent..I am aware of the answer you posted..your approach is a popular one (even I use)but I am just illustrating another approach
I agree that the title is not as specific. However, what I quoted came directly from the question. See the second, and last, sentence in the question. You do present an alternate approach which might be useful in a situation where the two elements do not have an ancestor<->descendant relationship.
event.target in example lead me to research more about "event", very resourceful answer!