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

如何在Shadow Root父元素中获取keyup事件的contenteditable目标元素?

如何在Shadow Root事件冒泡中获取实际触发的contenteditable元素?

我在Chrome扩展的content script中创建了一个Shadow Root,结构如下:

<div id="container" onkeyup="catchEventsFun">
  <div id="parent-1">
    <div contenteditable id="child-1"></div>
  </div>
  <div id="parent-2">
    <div contenteditable id="child-2"></div>
  </div>
  <div id="parent-3">
    <div contenteditable id="child-3"></div>
  </div>
</div>

问题:当child-2触发keyup事件时,catchEventsFun中捕获的event.target是Shadow Root元素,而非实际触发的子元素。

已尝试的方法:

  • 使用composedPath或path:path为null,composedPath返回空数组,event.composed为true,但无效
  • 使用event.currentTarget:返回null,无效

解决方案

方法1:移除内联事件,在Shadow DOM内部通过JS绑定事件监听器

内联事件处理器(onkeyup="catchEventsFun")运行在主文档的全局上下文,无法正确访问Shadow DOM内的事件目标。改为在Shadow Root内部直接绑定事件:

// 创建Shadow Root的content script代码
const hostElement = document.querySelector('#your-host-element'); // 替换为你的宿主元素
const shadowRoot = hostElement.attachShadow({ mode: 'open' });

// 插入Shadow DOM内容(包含container)
shadowRoot.innerHTML = `
<div id="container">
  <div id="parent-1">
    <div contenteditable id="child-1"></div>
  </div>
  <div id="parent-2">
    <div contenteditable id="child-2"></div>
  </div>
  <div id="parent-3">
    <div contenteditable id="child-3"></div>
  </div>
</div>
`;

// 获取container并绑定事件
const container = shadowRoot.getElementById('container');
container.addEventListener('keyup', catchEventsFun);

function catchEventsFun(event) {
  // 此时event.target就是实际触发事件的child元素
  console.log('触发元素:', event.target);
}

方法2:在Shadow DOM内部定义事件处理函数(保留内联事件的场景)

如果必须使用内联事件,需要将catchEventsFun定义在Shadow DOM的上下文内,让它能访问内部元素:

// 创建Shadow Root的content script代码
const hostElement = document.querySelector('#your-host-element');
const shadowRoot = hostElement.attachShadow({ mode: 'open' });

// 插入内容和脚本
shadowRoot.innerHTML = `
<div id="container" onkeyup="catchEventsFun(event)">
  <div id="parent-1">
    <div contenteditable id="child-1"></div>
  </div>
  <div id="parent-2">
    <div contenteditable id="child-2"></div>
  </div>
  <div id="parent-3">
    <div contenteditable id="child-3"></div>
  </div>
</div>
<script>
function catchEventsFun(event) {
  console.log('触发元素:', event.target);
}
</script>
`;

原因说明

内联事件的执行上下文是主文档全局,而Shadow DOM的内部元素对全局上下文是隔离的,导致事件的composedPath无法正确传递内部元素信息。将事件绑定或处理函数放在Shadow DOM内部上下文,就能直接获取到实际触发事件的元素。

内容的提问来源于stack exchange,提问作者Lerner Zhang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:15:15