<slot> 是 Web Components 中用于在 Shadow DOM 内投影 Light DOM 内容的声明式插入点,不跨文档、不修改原始 DOM、仅影响渲染;需配合 attachShadow() 和自定义元素注册才能生效。

HTML 插槽(<slot>)本身不支持跨文档或跨域的内容分发,它只在 Shadow DOM 内部起作用,用于组件内局部内容投影。
什么是 <slot>?它不是“分发”,是“投影”
<slot> 是 Web Components 规范中的一部分,作用是在自定义元素的 Shadow DOM 中预留内容插入点。它不会把内容“发送”到别处,也不会触发网络请求或 DOM 移动——只是把 Light DOM 中的节点“渲染到”指定 slot 位置。
- 父级 HTML 写的子内容(Light DOM)必须显式被
<slot>“接住”,否则会被丢弃(除非有<slot>不带name且未被占满) - 没有 JavaScript 参与时,
<slot>不会修改原始 DOM 结构,只影响渲染顺序 - 不能用
<slot>把内容从一个页面“推”到另一个页面,也不能替代iframe或服务端模板包含
<slot> 的 name 属性和默认插槽怎么配合使用
命名插槽(name="header")和匿名插槽(无 name)共存时,匹配逻辑容易出错。关键看 Light DOM 子元素是否带 slot 属性:
- 带
slot="header"的元素 → 只能进<slot name="header"> - 不带
slot属性的元素 → 进第一个匿名<slot>(如果存在),否则被丢弃 - 多个匿名
<slot>?只有第一个生效,其余被忽略
示例:
立即学习“前端免费学习笔记(深入)”;
<my-card> <h2 slot="title">标题</h2> <p>这是正文</p> </my-card> <p><!-- Shadow DOM 内 --> <slot name="title"></slot> <slot></slot> <!-- 匿名 slot 接收 <p> -->
为什么 <slot> 在 Vue/React 里“看起来像分发”?
因为框架封装了底层逻辑:Vue 的 <slot>、React 的 props.children 都是模拟插槽语义的抽象层,并非原生 <slot>。它们实际靠 props 传递 JSX/VDOM 片段,在组件 render 函数中拼接,和 Shadow DOM 无关。
- 原生
<slot>必须配合attachShadow()和自定义元素才能生效 - 直接在普通 HTML 中写
<slot>标签,浏览器会当成未知元素,不解析也不渲染 - Vue 单文件组件里的
<slot>是编译器识别的语法糖,最终转成函数调用,和 Web Components 无绑定
常见错误:插槽内容没显示,可能卡在这几个地方
插槽“失灵”往往不是语法错,而是上下文缺失:
- 忘了调用
element.attachShadow({mode: 'open'})—— 没 Shadow DOM,<slot>就是死标签 - 自定义元素未用
customElements.define()注册,导致浏览器不升级,Shadow DOM 不挂载 - Light DOM 子元素写了
slot="x",但 Shadow DOM 里没有对应<slot name="x">,内容就“消失”了(其实是被丢弃) - 用了
<slot>但没给 fallback 内容,而 Light DOM 又没传内容,结果渲染为空白,误以为失败
调试建议:打开 Chrome DevTools → Elements 面板 → 点开自定义元素 → 查看是否有 #shadow-root,再确认 Light DOM 子节点是否出现在 “Assigned nodes” 下(右键节点 → “Reveal in Shadow DOM”)。



















