event.target 是实际触发事件的最深节点,this(或event.currenttarget)是事件绑定的元素;target可能为文本节点或svg元素导致classlist失效,应使用closest()安全获取祖先元素。

event.target 指的是谁,和 this 不是一回事
绑定在 <ul></ul> 上的点击事件,用户点的是里面某个 <li> 里的 <span></span>,那 event.target 就是那个 <span></span>;而 this(或 event.currentTarget)始终是 <ul></ul>。两者在事件委托场景下几乎必然不同。
常见误判:以为 event.target 总是“你绑事件的那个元素”,结果取 event.target.dataset.id 报错——因为 target 其实是它里面的文本节点或图标 <svg></svg>。
为什么直接用 event.target.classList 可能失效
event.target 可能落到非元素节点上,比如:
- 点击带 padding 的卡片区域,实际触发的是内部的文本节点(
Node.TEXT_NODE),此时event.target.tagName是undefined,classList会报Cannot read property 'contains' of null - 点击按钮内的
<svg></svg>或<path></path>,event.target是 SVG 元素,没有你预期的btn类名 - 没加边界判断就连续调
event.target.parentElement.parentElement,可能走到null或document导致后续操作崩溃
安全获取语义化容器的写法:closest() 是首选
不用手动往上爬父级,event.target.closest('selector') 从 target 自身开始向上匹配第一个符合条件的祖先(含自身),返回 null 表示没找到,天然防崩。
示例:表格行点击委托
table.addEventListener('click', e => {
const row = e.target.closest('tr');
if (!row) return;
console.log('点击的行ID:', row.dataset.id);
});
注意兼容性:closest() 在 IE 中不支持;如需兼容,得用 polyfill,或降级为 matches() + 循环查找。
自定义事件里 event.target 不是你想的那样
原生事件(如 click、input)自动设置 event.target 为 dispatchEvent() 调用时传入的元素;但自定义事件(new CustomEvent())默认不携带有效 target——除非你显式指定 bubbles: true 并确保 dispatch 到具体 DOM 元素上。
更现实的做法是把源头信息塞进 detail 字段:
el.dispatchEvent(new CustomEvent('item-selected', {
detail: { source: clickedBtn, id: 'abc123' }
}));
这时候别依赖 event.target 去反推触发者,它只是 dispatch 的宿主,不是用户真正点的那个东西。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











