You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS事件冒泡:如何避免点击目标元素变化的问题?

问题:点击按钮子元素时无法获取父按钮的data属性

我给点赞、点踩按钮绑定了click事件,但点击按钮内的<span>区域时,ev.target指向的是子元素,拿不到父按钮上的data-item-id。试过ev.stopPropagation()没用,怎么解决?

解决方法

1. 用event.currentTarget替代event.target

currentTarget永远指向绑定事件监听器的元素(也就是你绑定点击事件的按钮),不管点击的是它的哪个子元素,直接用它就能拿到按钮上的data-item-id。

2. 通过closest()定位父按钮

如果需要从点击的子元素往上找到对应的按钮,可以用ev.target.closest('.comment-vote-up')(点赞按钮)或ev.target.closest('.comment-vote-down')(点踩按钮),这个方法会返回匹配选择器的最近祖先元素。

3. 事件委托(更简洁的批量处理方式)

把事件监听器绑定到父容器上,通过判断点击元素的祖先是否是目标按钮来处理,适合多个按钮的场景,减少重复绑定事件。

修改后的代码示例

方法1:使用currentTarget

const commentVotes = document.querySelectorAll('.comment-votes');

commentVotes.forEach((row) => {
  const up = row.querySelector('.comment-vote-up');
  const down = row.querySelector('.comment-vote-down');            

  up.addEventListener('click', async (ev) => {    
    const id = ev.currentTarget.getAttribute('data-item-id');
    console.log({"target": ev.currentTarget, "ID": id})
  });
  
  down.addEventListener('click', async (ev) => {
    const id = ev.currentTarget.getAttribute('data-item-id');
    console.log({"target": ev.currentTarget, "ID": id})
  })
});

方法2:使用closest()

const commentVotes = document.querySelectorAll('.comment-votes');

commentVotes.forEach((row) => {
  const up = row.querySelector('.comment-vote-up');
  const down = row.querySelector('.comment-vote-down');            

  up.addEventListener('click', async (ev) => {    
    const button = ev.target.closest('.comment-vote-up');
    const id = button.getAttribute('data-item-id');
    console.log({"target": button, "ID": id})
  });
  
  down.addEventListener('click', async (ev) => {
    const button = ev.target.closest('.comment-vote-down');
    const id = button.getAttribute('data-item-id');
    console.log({"target": button, "ID": id})
  })
});

方法3:事件委托

document.querySelector('.comment-votes').addEventListener('click', async (ev) => {
  const upButton = ev.target.closest('.comment-vote-up');
  const downButton = ev.target.closest('.comment-vote-down');
  
  if (upButton) {
    const id = upButton.getAttribute('data-item-id');
    console.log({"action": "like", "ID": id});
  } else if (downButton) {
    const id = downButton.getAttribute('data-item-id');
    console.log({"action": "dislike", "ID": id});
  }
});

原HTML结构

<div class="comment">
  <div class="comment-vote-box comment-votes mt-10">
    
    <div class="vote-up">
      <button class="comment-vote-up" data-item-id="11">
        <span class="spacer">Like</span>
        <span>0</span>
      </button>
    </div>
    
    <div class="vote-down">
      <button class="comment-vote-down" data-item-id="12">
        <span class="spacer">Dislike</span>
        <span>1</span>
      </button>
    </div>
    
  </div>
</div><!-- comment -->

原CSS样式

.comment .comment-vote-box {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
}

.spacer {
  margin-right:10px;
}

内容的提问来源于stack exchange,提问作者Max Pattern

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 15:30:52