
当页面中存在多层 Shadow DOM 时,document.activeElement 默认只返回最外层宿主元素,而非内部实际聚焦的表单控件;需递归遍历 shadowRoot 才能定位到真正的活跃元素。
当页面中存在多层 shadow dom 时,`document.activeelement` 默认只返回最外层宿主元素,而非内部实际聚焦的表单控件;需递归遍历 shadowroot 才能定位到真正的活跃元素。
在现代 Web 组件开发中,Shadow DOM 提供了强大的封装能力,但也带来了焦点追踪的复杂性。原生 解决方法无需额外监听事件或手动遍历 DOM 树。核心逻辑简洁而可靠:从 以下是一个健壮的工具函数实现: ✅ 关键要点说明: ⚠️ 注意:避免在 总之,掌握这一递归穿透技巧,即可在任意深度的 Shadow DOM 结构中精准定位用户交互焦点,是构建可访问、可测试 Web Components 的基础能力之一。document.activeElement 无法穿透 Shadow Boundary——它始终返回当前文档中最顶层的聚焦宿主节点(例如 。document.activeElement 出发,逐级检查其 shadowRoot 是否存在,并持续访问其内部的 .activeElement,直到抵达无 Shadow Root 的终端元素。function getDeepActiveElement() {
let el = document.activeElement;
while (el && el.shadowRoot && el.shadowRoot.activeElement) {
el = el.shadowRoot.activeElement;
}
return el;
}
// 使用示例
window.addEventListener('focus', () => {
const deepActive = getDeepActiveElement();
console.log('真正聚焦的元素:', deepActive);
}, true);
el 为 null、无 shadowRoot,或 shadowRoot.activeElement 为 null(如 Shadow Root 内无聚焦元素),循环立即终止; open / closed),但仅 open 模式下可读取 shadowRoot.activeElement(closed 模式会返回 null,此时自然终止); focusin/focus 事件处理器中直接修改 DOM 或触发重排,否则可能引发意外行为;如需响应焦点变化,建议使用 getDeepActiveElement() 获取目标后做纯逻辑处理。










