标准答案

  1. event.target 表示事件最初发生的目标节点,可能是按钮里的图标、文字节点或更深层的子元素。
  2. event.currentTarget 表示当前正在执行监听器的绑定节点。监听器绑在哪个元素上,执行这个监听器时 currentTarget 就是谁。
  3. 事件代理通常把监听器绑在父容器上。子元素触发事件后冒泡到父容器,currentTarget 是父容器,target 是实际触发事件的子节点。
  4. 代理逻辑通常用 target.closest 或 matches 找到符合条件的子项,再用 container.contains 做边界校验。这样可以统一处理已有子项和动态新增子项。

题目解析

事件代理依赖事件冒泡。不是所有事件都适合代理,例如 focus/blur 默认不冒泡,可以考虑 focusin/focusout 或捕获阶段。

target 不一定是你业务上想处理的元素。按钮里有 svg、span 或图标时,target 可能落在内部节点上,所以通常用 closest 找到带业务标记的元素。

代理时要校验目标仍在当前容器内。嵌套列表或多个容器共享选择器时,只靠 closest 可能误处理其它区域的元素。

代码示例

下面示例把监听器绑定在列表容器上,通过 target.closest 找到真实操作按钮。

JavaScript
const list = document.querySelector('#todo-list')

list.addEventListener('click', (event) => {
  const button = event.target.closest('[data-action="remove"]')

  if (!button || !list.contains(button)) {
    return
  }

  console.log(event.currentTarget === list) // true
  console.log(event.target) // 实际点击到的内部节点

  button.closest('li')?.remove()
})

常见误区

  • 把 target 和 currentTarget 当成同一个元素。
  • 事件代理时不检查目标是否属于当前容器。
  • 点击嵌套元素时直接读取 target.dataset,导致读不到期望字段。

作者信息