最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - trigger event only on parent click not child - Stack Overflow

programmeradmin4浏览0评论

Consider the following code as an example:

<div id="parent">
  <div id="child">info goes here</div>
</div>

//javascript
function something{
//do something;}
//initial attempt
document.getElementById('parent').addEventListener('click',something);
//event capture
document.getElementById('parent').addEventListener('click',something,true);

When I click on the parent element I would like it to do something, and when I click the child I want it to do nothing. The problem is that when I click in the child element it is triggering 'something'. I thought that it may be event bubbling, such that if I clicked on the child element, the event would bubble up from there to the parent. So then I was thinking about an event capture, but that also causes this problem.

Any advice or suggestions on how to acplish this would be greatly appreciated.

Consider the following code as an example:

<div id="parent">
  <div id="child">info goes here</div>
</div>

//javascript
function something{
//do something;}
//initial attempt
document.getElementById('parent').addEventListener('click',something);
//event capture
document.getElementById('parent').addEventListener('click',something,true);

When I click on the parent element I would like it to do something, and when I click the child I want it to do nothing. The problem is that when I click in the child element it is triggering 'something'. I thought that it may be event bubbling, such that if I clicked on the child element, the event would bubble up from there to the parent. So then I was thinking about an event capture, but that also causes this problem.

Any advice or suggestions on how to acplish this would be greatly appreciated.

Share Improve this question edited May 8, 2019 at 0:55 nCoder 1069 bronze badges asked May 7, 2019 at 23:10 Paul CarlsonPaul Carlson 4576 silver badges25 bronze badges 1
  • 2 Possible duplicate of How do I prevent a parent's onclick event from firing when a child anchor is clicked? – Michelangelo Commented May 7, 2019 at 23:29
Add a ment  | 

3 Answers 3

Reset to default 9

Instead, add the event only to the parent element, and check if the element originating the event Event.target.closest(selector) - was indeed the desired element selector.
PS: Don't confuse Event.target with Event.currentTarget which (in contrast) is always the Element who has the Event handler attached.

const elParent = document.querySelector("#parent");

function doStuff(evt) {
  if (evt.target.closest("#child")) {
    console.log("Do child stuff only");
  } else {
    console.log("Do parent stuff only (not if child is clicked)");
  }
}

elParent.addEventListener("click", doStuff);

// Additional example on why you should avoid `Event.stopPropagation()`:
document.body.addEventListener("click", () => {
  console.log("(App was notified) Closing some opened popup, etc");
});
// and BODY should always be notified about events! And this works as expected.
#parent, #child {
  padding: 1rem;
  outline: 1px solid red;
}
<div id="parent">
  <b>PARENT</b> ELEMENT
  <div id="child">CHILD ELEMENT</div>
</div>

Don't use Event.stopPropagation()

Event.stopPropagation() would be an idea, but a bad one. We should avoid an application layer to not register an event that occurred deeper in the DOM tree. We should let an event to freely bubble - and eventually notify other elements that such an event happened.
Imagine a body listening for click events in order to close a recently opened custom dropdowns, modal, etc. If you have elements wandering around your app that use Event.stopPropagation() - clicking on such an element the opened dropdown would not close, resulting in a broken UI. And this was just a simple example.
Of course one could catch an event on app-level even if a ponent uses Event.stopPropagation() by using the Event capture phase {capture: true}, but not many developers do so.

Here's a discouraged(!) way to use Event.stopPropagation() but still catch events on app-wise-level:

const elParent = document.querySelector("#parent");
const elChild = document.querySelector("#child");

function doChildStuff(evt) {
  evt.stopPropagation(); // DISCOURAGED. Avoid 
  console.log("Do child stuff only");
}

function doParentStuff(evt) {
  console.log("Do parent stuff");
}

elChild.addEventListener("click", doChildStuff);
elParent.addEventListener("click", doParentStuff);

// Additional example: proper planning for `Event.stopPropagation()`:
document.body.addEventListener("click", () => {
  console.log("(App was notified) Closing some opened popup, etc");
}, {capture: true}); // PROPER WAY, since we use Event.stopPropagation()
#parent, #child {
  padding: 1rem;
  outline: 1px solid red;
}
<div id="parent">
  <b>PARENT</b> ELEMENT
  <div id="child">CHILD ELEMENT</div>
</div>

Use event.stopPropagation to stop event bubbling:

function something() {
  console.log("something");
}
document.getElementById('parent').addEventListener('click', something);
document.getElementById('child').addEventListener('click', e => e.stopPropagation());
<div id="parent">
  Parent info goes here!
  <div id="child">Child info goes here!</div>
</div>

It is event bubbling. Just because you are handling the click event on the child, does not mean it stops bubbling to the parent.

There are two approaches to this. The first one is to stop the event from propagating like this: document.getElementById('child').addEventListener('click',(e) => { e.stopPropagation(); something() },true);

The second is to check the event target and only run something when the deepest element that caused the click event is the child element:

document.getElementById('child').addEventListener('click',(e) => { e.target.id == "child" ? something() : nothing() },true);

发布评论

评论列表(0)

  1. 暂无评论