JavaScript 操作 Shadow DOM 需先用 attachShadow()创建影子根并指定 open/closed 模式,再通过 shadowRoot 使用标准 DOM 方法操作;两者与主 DOM 隔离,可通过自定义事件、slot 和:host 等机制通信与样式穿透。

JavaScript 操作 Shadow DOM 主要靠 attachShadow() 创建影子根,再用标准 DOM 方法往里面添加和查询元素。
创建 Shadow DOM
调用 element.attachShadow() 方法为元素挂载影子根。必须传入 {mode: ‘open’} 或 {mode: ‘closed’}:
- open 模式下,可通过
element.shadowRoot直接访问影子根,支持常规 DOM 操作 - closed 模式下,
shadowRoot返回null,外部 JS 无法访问内部结构(仅组件内部能操作)
示例:
const host = document.getElementById('my-host'); const shadow = host.attachShadow({mode: 'open'}); // 创建 open 模式 Shadow DOM shadow.innerHTML = `<p>Hello from Shadow DOM!</p><p><span> 立即学习 </span>“<a href="https://pan.quark.cn/s/c1c2c2ed740f" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">Java 免费学习笔记(深入)</a>”;</p>`;
在 Shadow DOM 中操作节点
一旦拿到 shadowRoot,就能像操作普通 DOM 一样使用 querySelector、appendChild、addEventListener 等方法:
- 添加内容:
shadow.appendChild(document.createElement('div')) - 查找元素:
shadow.querySelector('button')(只在影子树内查找) - 监听事件:
shadow.addEventListener('click', handler),或绑定到内部按钮上
注意:document.querySelector() 查不到影子树里的节点,反之亦然——两者是隔离的。
跨边界通信与样式穿透
Shadow DOM 默认有样式和脚本 作用域 隔离,但仍有可控方式交互:
- 通过 自定义事件 向外派发:
host.dispatchEvent(new CustomEvent('data-ready', { detail: data})) - 用 slot 让外部 HTML“透传”进 Shadow DOM:
<slot></slot>占位,外部内容自动渲染其中 - 样式方面,
:host选中宿主元素,::slotted(p)可样式化插槽中的 p 标签,但无法用外部 CSS 直接选中内部元素
检查与调试技巧
Chrome/Firefox 开发者 工具 默认会显示 Shadow DOM(需开启“Show user agent shadow DOM”设置):
- 在 Elements 面板中,带“#shadow-root”标记的节点就是影子根
- 右键影子根 →“Break on”→“subtree modifications”,可监听内部变动
- 控制台中输入
$0.shadowRoot(选中宿主元素后),快速访问当前影子根
基本上就这些。不复杂但容易忽略 mode 选项和作用域边界。