slot标签仅在shadow dom中生效,必须配合customelements.define()注册自定义元素、调用attachshadow({mode:'open'})、且写在shadow dom内部,三者缺一即静默失效。

slot 标签在普通 HTML 中什么也不做,它只在 Shadow DOM 里生效——没挂 attachShadow(),写了也白写。
为什么 slot 完全没反应?
最常见原因是把它当普通标签用了:直接写在页面里、塞进 <div> 中、或放在未注册的自定义标签内部。浏览器会静默忽略,不报错也不警告。
<ul><li>必须用 <code>customElements.define() 注册合法自定义元素(如 <my-card></my-card>),不能对 <div> 或 <code><p></p> 调用 attachShadow(),否则抛出 DOMException: This element does not support shadow roots
attachShadow({ mode: 'open' }) 必须在 constructor 或 connectedCallback 中执行,且只能调一次<slot></slot> 必须出现在 Shadow DOM 内部(比如通过 shadowRoot.appendChild(template.content.cloneNode(true)) 插入),不能写在 Light DOM 里
slot 内容不显示,检查直系子节点和 name 匹配
外部内容必须是自定义元素的**直系子元素**,且 slot 属性值与 name 严格相等(区分大小写、首尾空格敏感)。
- ✅ 正确:
<my-card><h2 slot="header">标题</h2></my-card> - ❌ 失效:
<my-card><div><h2 slot="header">标题</h2></div></my-card>(<h2></h2>是孙节点) - ❌ 失效:
<slot name="Header"></slot>不匹配<h2 slot="header"></h2>(大小写不一致) - ❌ 失效:
<slot name="header"></slot>不匹配<h2 slot="header "></h2>(末尾空格) - 没写
name的<slot></slot>默认name="default",只收所有未带slot属性的直系子节点
怎么查 slot 是否真被填满了?
别只看渲染结果;assignedNodes() 在初始化时大概率为空,因为分发还没完成。
- 监听
slotchange事件才是可靠时机:slot.addEventListener('slotchange', () => { console.log(slot.assignedNodes({ flatten: true })); }) -
assignedNodes()默认不展开嵌套结构,必须加{ flatten: true }才能拿到所有最终投射进来的节点(包括 fallback 内容里的节点) -
slotchange不冒泡、不捕获,也不能在shadowRoot上监听,必须绑定到具体<slot></slot>元素上 - Firefox 63 以下不支持
slotchange,需降级用MutationObserver监听slot的childList
真正卡住人的地方,往往不是语法写错,而是层级多了一层、换行符变成了文本节点、或者 attachShadow() 没在正确生命周期里调用——这些都不会报错,但内容就“消失”了。











