仅在父级点击而非子级点击时触发事件

Pau*_*son 4 html javascript dom addeventlistener

以以下代码为例:

<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);
Run Code Online (Sandbox Code Playgroud)

当我单击父元素时,我希望它执行某些操作,而当我单击子元素时,我希望它不执行任何操作。问题是,当我单击子元素时,它会触发“某些内容”。我认为这可能是事件冒泡,这样如果我单击子元素,事件就会从那里冒泡到父元素。于是我就想到了事件捕获,但这也导致了这个问题。

任何有关如何实现这一目标的意见或建议将不胜感激。

Rok*_*jan 8

相反,仅将事件添加到父元素,并检查发起事件的元素Event.target.closest(selector)是否确实是所需的元素选择器
PS:不要Event.targetEvent.currentTarget混淆,后者(相反)始终是附加了事件处理程序的元素。

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.
Run Code Online (Sandbox Code Playgroud)
#parent, #child {
  padding: 1rem;
  outline: 1px solid red;
}
Run Code Online (Sandbox Code Playgroud)
<div id="parent">
  <b>PARENT</b> ELEMENT
  <div id="child">CHILD ELEMENT</div>
</div>
Run Code Online (Sandbox Code Playgroud)

不要使用Event.stopPropagation()

Event.stopPropagation()这将是一个想法,但却是一个糟糕的想法。我们应该避免应用程序层不注册 DOM 树更深处发生的事件。我们应该让事件自由冒泡,并最终通知其他元素此类事件发生了。
想象一下,body监听点击事件以关闭最近打开的自定义下拉菜单、模式等。如果您的应用程序中存在使用的元素,则Event.stopPropagation()单击这样的元素,打开的下拉菜单将不会关闭,从而导致UI 损坏。这只是一个简单的例子。
当然,即使组件使用事件捕获阶段,也可以在应用程序级别捕获事件,但这样做的开发人员并不多。Event.stopPropagation(){capture: true}

这是一种不推荐的(!)使用方法Event.stopPropagation(),但仍然可以捕获应用程序级别的事件:

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()
Run Code Online (Sandbox Code Playgroud)
#parent, #child {
  padding: 1rem;
  outline: 1px solid red;
}
Run Code Online (Sandbox Code Playgroud)
<div id="parent">
  <b>PARENT</b> ELEMENT
  <div id="child">CHILD ELEMENT</div>
</div>
Run Code Online (Sandbox Code Playgroud)


Jac*_*ord 5

用于event.stopPropagation停止事件冒泡:

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