slot插槽本身不构成web components,它仅在shadow dom内生效,需通过this.attachshadow({mode:'open'})启用,且内容必须是自定义元素的直系子元素,命名须含短横线、大小写严格匹配。

slot 插槽本身不构成 Web Components,它只是其中一环;没注册自定义元素、没挂 Shadow DOM,slot 就是段被忽略的静态标签——页面上啥也不显示,控制台还不报错。
为什么写了 slot 却什么都没渲染出来
这是最常卡住人的第一步。根本原因不是代码写错了,而是环境没搭对:
-
slot只在 Shadow DOM 内生效,必须调用this.attachShadow({ mode: 'open' }),且只能在constructor中执行一次 - 外部传入的内容必须是自定义元素的**直系子元素**:
<my-modal><h2 slot="title">弹窗</h2></my-modal>✅;<my-modal><div><h2 slot="title">弹窗</h2></div></my-modal>❌(h2是孙节点,不参与分发) -
slot元素必须出现在 Shadow DOM 模板里,不能写在 Light DOM 中(比如直接塞进<my-modal></my-modal>标签内部) - 自定义元素名必须含短横线,且全小写:
my-modal✅,myModal或modal❌(会直接抛Failed to execute 'define')
slot 的 name 匹配是精确字符串比对,大小写敏感
具名插槽不是“模糊匹配”,name="header" 和 slot="Header" 完全不搭界:
-
<slot name="title"></slot>只接收<h2 slot="title">xxx</h2>,slot="Title"或slot="title-text"都无效 - 没带
slot属性的元素(如<p>正文</p>)只会尝试填入第一个无name的<slot></slot>;后面再多空<slot></slot>也收不到 - 多个同名
<slot name="item"></slot>时,Light DOM 中每个slot="item"元素按顺序依次填入一个slot,不是复制广播 - 未被任何
<slot></slot>匹配的节点,保留在 Light DOM 中但完全不参与渲染(不是隐藏,是跳过)
::slotted() 样式只能作用于投射内容的直接子元素
想给外部传进来的标题加颜色?别写 h2 { color: red; }(污染全局),也别指望 ::slotted(div h2) 能生效:
- 正确写法:
::slotted(h2)、::slotted([slot="footer"])、::slotted(.btn) - 错误写法:
::slotted(div h2)、::slotted(h2 > span)、::slotted(*)(通配符无效) -
::slotted()只在 Shadow DOM 的样式表中有效,且只捕获“被投射进来”的节点,不包括slot自身或 fallback 内容 - 若需更细粒度样式控制,要么让传入内容自带
class,要么在组件内用slot.assignedNodes({ flatten: true })手动遍历处理
真正容易被忽略的是时机问题:slotchange 事件才是内容分发完成的可靠信号;在 connectedCallback 里立刻调 slot.assignedNodes(),大概率拿到空数组——因为此时分发还没开始。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











