Shadow DOM 是 Web Components 的核心封装机制,通过 attachShadow() 创建隔离的影子树实现样式与结构隔离,支持 open/closed 模式、:host/::slotted 伪类、slot 内容分发,并常与 Custom Elements 结合构建自治组件。

Shadow DOM 是 Web Components 的核心机制之一,它通过创建一个与主文档 DOM 隔离的“影子树”,实现真正的样式和结构封装,避免全局污染和意外覆盖。
Shadow DOM 的基本创建方式
每个元素可通过 attachShadow() 方法挂载一个 Shadow Root,从而开启封装边界:
- 使用
{ mode: 'open' }时,可通过element.shadowRoot在外部访问影子树,便于调试和测试 - 使用
{ mode: 'closed' }时,shadowRoot属性返回null,完全隐藏内部实现(但实际中调试困难,较少推荐) - 一个元素最多只能有一个 Shadow Root,重复调用会抛出错误
样式隔离:天然的 Scoped CSS
Shadow DOM 内部定义的 CSS 默认不会影响外部,外部样式也默认无法穿透进来(除非显式使用 ::slotted 或 :host 等伪类):
-
:host匹配宿主元素自身,可用于设置组件根节点样式或响应状态(如:host([disabled])) -
::slotted(selector)选择被<slot>投入的内容节点(注意:只匹配顶层子元素,不递归) - 外部无法用
.my-component div选中影子树内的 div,除非使用/deep/(已废弃)或::part()+exportparts(现代替代方案)
内容分发:slot 是连接内外的桥梁
<slot> 元素定义内容插入点,支持具名插槽与默认插槽:
立即学习“Java免费学习笔记(深入)”;
- 无
name的<slot>为默认插槽,接收所有未匹配的子节点 - 带
name="header"的插槽,只接收<div slot="header">这类标记的节点 - 可通过
slot.assignedNodes({ flatten: true })获取实际渲染的内容节点,用于动态处理(如统计、修饰)
与 Custom Elements 结合构建完整组件
Shadow DOM 通常配合 customElements.define() 使用,形成可复用、自治的 Web Component:
- 在自定义元素构造函数中调用
this.attachShadow({ mode: 'open' }),并填充模板或动态生成结构 - 可监听
attributeChangedCallback响应属性变化,并同步更新 shadow 内容或样式 - 避免在 shadow 中直接操作
document,应优先使用this.shadowRoot进行查询和事件绑定
不复杂但容易忽略:Shadow DOM 不是黑盒,它遵循标准 DOM API,只是加了一层作用域边界。理解它的边界行为,比记住语法更重要。










