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

时间:2017-05-30 19:01:25

标签: javascript event-handling addeventlistener event-bubbling event-capturing

我试图从根元素中捕获每张卡上的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>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:2)

是的,一个听众是一个很好的要求。碰巧你只需要改变你获得目标的那条线:

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>

答案 1 :(得分:0)

问题在于,根据您点击的位置,您可能会点击<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

&#13;
&#13;
Array.prototype.slice.call(document.querySelectorAll(".card")).forEach(function(c){
  c.addEventListener('click', evt => {
    console.log(evt.currentTarget.id);
  });
});
&#13;
.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;
}
&#13;
<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>
&#13;
&#13;
&#13;