具有嵌套元素的根元素上的事件冒泡和捕获

Event bubbling and capture on a root element with nested elements

我正在尝试从根元素捕获每张卡片上的 ID。但是,每次单击嵌套元素时,我都会得到空字符串。但是,我想在监听根元素卡时从包装卡中获取 id。我想同时处理冒泡和捕获案例,因为这是更大结构的一部分。我只想要 vanilla js 和 Javascript 的答案,请不要 css。

cards.addEventListener('click', evt => {
  if (evt.target !== evt.currentTarget) {
    var clickedItem = evt.target.id
    console.log(clickedItem);
  }
});
.card {
  /* Add shadows to create the "card" effect */
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
  transition: 0.3s;
}


/* On mouse-over, add a deeper shadow */

.card:hover {
  box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
}


/* Add some padding inside the card container */

.container {
  padding: 2px 16px;
}
<div id="cards" style="margin: auto; width: 50%;">
  <div class="card" id="1234567"><img src="img_avatar.png">
    <div class="container">
      <h4>1st Note</h4>
      <p>Note Body</p>
    </div>
  </div>
  <div class="card" id="1234547"><img src="img_avatar.png">
    <div class="container">
      <h4>2nd Note</h4>
      <p>Note Body2</p>
    </div>
  </div>
  <div class="card" id="721680"><img src="img_avatar.png">
    <div class="container">
      <h4>3Note Body</h4>
      <p>Note Body3</p>
    </div>
  </div>
</div>

问题是,根据您点击的位置,您最终可能会点击 <div class="container">,但没有 id

让我们检查一下您的 HTML 结构:

<!-- You have your click handler attached to this parent element. It's true
     that any clicks on descendant elements will bubble up to this parent, 
     but when you handle it here, this parent becomes event.currentTarget 
     and while this element does have an id, it's not the id you want. -->
<div id="cards" style="margin: auto; width: 50%;">

  <!-- This is the element level that has the id that you want, so
       this is the element level that should have the event handlers. -->
  <div class="card" id="1234567">

    <!-- If the user clicks in the area of the following elements (which 
         they are most likely to because it takes up most of the space 
         on the card) one of these elements will become `event.target` 
         and none of these elements has an id to get. That's why you are
         getting an empty string in your console. -->
    <img src="img_avatar.png">

    <div class="container">
      <h4>1st Note</h4>
      <p>Note Body</p>
    </div>

  </div>

  ... inner pattern repeats ...

</div>

您需要将点击事件分配给每个 .card,而不是父 .cards,然后您可以获得 currentTarget.id

Array.prototype.slice.call(document.querySelectorAll(".card")).forEach(function(c){
  c.addEventListener('click', evt => {
    console.log(evt.currentTarget.id);
  });
});
.card {
  /* Add shadows to create the "card" effect */
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
  transition: 0.3s;
}


/* On mouse-over, add a deeper shadow */

.card:hover {
  box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
}


/* Add some padding inside the card container */

.container {
  padding: 2px 16px;
}
<div id="cards" style="margin: auto; width: 50%;">
  <div class="card" id="1234567"><img src="img_avatar.png">
    <div class="container">
      <h4>1st Note</h4>
      <p>Note Body</p>
    </div>
  </div>
  <div class="card" id="1234547"><img src="img_avatar.png">
    <div class="container">
      <h4>2nd Note</h4>
      <p>Note Body2</p>
    </div>
  </div>
  <div class="card" id="721680"><img src="img_avatar.png">
    <div class="container">
      <h4>3Note Body</h4>
      <p>Note Body3</p>
    </div>
  </div>
</div>

是的,一个听众是一个很好的要求。碰巧您只需要更改获得目标的行:

cards.addEventListener('click', evt => {
  console.log( evt.target.closest( '.card' ).id );
});

完整示例:

cards.addEventListener('click', evt => {
  alert( evt.target.closest( '.card' ).id );
});
.card {
  /* Add shadows to create the "card" effect */
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
  transition: 0.3s;
}


/* On mouse-over, add a deeper shadow */

.card:hover {
  box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
}


/* Add some padding inside the card container */

.container {
  padding: 2px 16px;
}
<div id="cards" style="margin: auto; width: 50%;">
  <div class="card" id="1234567"><img src="img_avatar.png">
    <div class="container">
      <h4>1st Note</h4>
      <p>Note Body</p>
    </div>
  </div>
  <div class="card" id="1234547"><img src="img_avatar.png">
    <div class="container">
      <h4>2nd Note</h4>
      <p>Note Body2</p>
    </div>
  </div>
  <div class="card" id="721680"><img src="img_avatar.png">
    <div class="container">
      <h4>3Note Body</h4>
      <p>Note Body3</p>
    </div>
  </div>
</div>