slot元素是Web Components中实现内容投影的唯一原生机制,通过声明式、静态匹配将Light DOM内容视觉投射到Shadow DOM指定位置,需满足创建Shadow DOM、直系子元素、slot位于Shadow DOM内三前提。

slot 元素是 Web Components 中实现原始内容投影(content projection)的唯一原生机制,它不移动节点、不复制结构,而是通过浏览器内置规则将 Light DOM 中的内容“视觉上投射”到 Shadow DOM 的指定位置。关键在于理解它是声明式、静态匹配、且严格依赖 DOM 层级与属性字面量的分发通道。
必须满足的三个前提条件
slot 不会自动生效,缺一不可:
- 自定义元素内部必须调用
this.attachShadow({ mode: 'open' })创建影子根;没有 Shadow DOM,slot 标签只是普通未识别标签,完全被忽略 - 外部传入的内容必须是该自定义元素的直系子元素;嵌套在
<div>或其他元素内会被跳过,不参与分发 -
<slot>必须写在 Shadow DOM 模板中(如shadowRoot.innerHTML或<template>内),不能出现在 Light DOM 里
具名插槽与默认插槽的精准匹配逻辑
内容分发靠的是属性值的精确字符串比对,不是模糊查找或大小写容错:
- 具名插槽:
<slot name="header"></slot>只接收 Light DOM 中<h1 slot="header">...这类显式带slot="header"的元素 - 默认插槽:
<slot></slot>(无 name)只接收所有未带 slot 属性的直系子元素,且整个组件中只能有一个有效,默认插槽多余部分会被忽略 - 多个同名
<slot name="item">时,Light DOM 中每个slot="item"元素按顺序依次填入——第一个元素进第一个 slot,第二个进第二个,以此类推 - 未被任何 slot 匹配的节点保留在 Light DOM 中,但完全不渲染,不是隐藏,是跳过布局与绘制
控制投射内容的样式与行为
投射进来的内容仍属于 Light DOM 上下文,样式和事件路径不受 Shadow DOM 封装影响,但可通过以下方式干预:
- 使用
::slotted()伪元素为投射节点加样式,例如::slotted(h2)或::slotted([slot="footer"]) -
::slotted()不支持后代选择器(如::slotted(div h2)无效),也不支持通配符* - 事件冒泡仍沿 Light DOM 路径向上,不会穿透进 Shadow DOM;若需响应,应在 Light DOM 父节点监听,或由投射内容自身触发自定义事件
- slot 内可写 fallback 内容,如
<slot>暂无内容</slot>,仅当无匹配节点时显示
获取与响应投射内容的变化
slot 本身不提供数据接口,需手动查询和监听:
- 监听
slotchange事件:仅在 Light DOM 子元素增删时触发,首次渲染不触发,且事件不冒泡,必须直接绑定在 slot 元素上 - 调用
slot.assignedNodes({ flatten: true })获取当前已分发的真实节点列表(含文本节点),注意返回的是静态 NodeList,需重新调用才能反映最新状态 - 若需提取结构化信息(如
data-id值或输入框值),必须遍历assignedNodes()结果,自行解析node.dataset或node.value - JS 动态插入内容(如
element.appendChild())不会自动触发slotchange,需手动检查或延迟读取

















