点击事件监听中e.target.name在子元素触发时返回undefined的原因及属性选择咨询
点击按钮内图标时
e.target.name返回undefined的原因及解决方案 问题现象
我遇到一个问题:点击按钮本身时能通过e.target.name拿到正确结果,但点击按钮内部的图标元素时,e.target.name却返回undefined。想请教这一现象的原因是什么?是否应该使用其他属性来定位按钮和图标?
相关代码
JavaScript 代码
const scissorsEl = document.querySelector(".icon-scissors"); scissorsEl.addEventListener("click", (e) => { state.setUserChoice(e.target.name); console.log("label:", e.target.name); }); const state = { userChoice: "", setUserChoice(choice) { this.userChoice = choice; }, }
HTML 代码
<script src="https://kit.fontawesome.com/03a64a1742.js" crossorigin="anonymous"></script> <button class="icon icon-scissors" name="scissors"> <i class="fa-solid fa-hand-scissors" name="scissors"></i> </button>
原因分析
这是事件冒泡机制结合e.target的特性导致的:
e.target指向的是实际触发事件的DOM元素:点击按钮本身时,触发事件的是<button>元素,它自带标准的name属性,所以能正常取值;但点击内部<i>图标时,触发事件的是这个<i>标签——而<i>属于行内元素,本身并不支持标准的nameDOM属性,哪怕你手动写了name="scissors",浏览器也不会把它解析为元素的name属性,自然返回undefined。
解决方案
这里有几个实用的处理方式:
1. 用e.currentTarget替代e.target
e.currentTarget指向的是绑定事件监听的那个元素(也就是你选中的.icon-scissors按钮),不管事件是从哪个子元素冒泡上来的,它始终指向绑定监听的父元素。修改代码如下:
scissorsEl.addEventListener("click", (e) => { state.setUserChoice(e.currentTarget.name); console.log("label:", e.currentTarget.name); });
这样不管点击按钮还是内部图标,都能稳定拿到按钮的name值,而且你完全可以删掉<i>标签上多余的name属性(本来就不生效)。
2. 利用事件委托(多按钮场景更高效)
如果页面上有多个类似的选择按钮(比如剪刀、石头、布),可以把事件监听绑定到它们的父元素上,通过e.target.closest('button')精准定位到触发的按钮:
// 假设按钮的父容器类名为.game-buttons document.querySelector(".game-buttons").addEventListener("click", (e) => { const targetButton = e.target.closest('button[name]'); if (targetButton) { state.setUserChoice(targetButton.name); console.log("label:", targetButton.name); } });
这种方式不用给每个按钮单独绑定监听,性能更优,还能避免子元素干扰。
3. 清理无效属性
既然<i>标签不支持name属性,直接删掉图标上的name="scissors",减少代码冗余和混淆。
内容的提问来源于stack exchange,提问作者Franosan
相关产品推荐
相关产品推荐

