槽位映射是slot元素与light dom子节点间单向、静态、大小写敏感的匹配行为;仅在shadow dom初始化时按slot属性值抓取直系子节点并渲染,匹配失败则静默丢弃。

槽位映射(slot mapping)不是独立功能,而是 slot 元素与 Light DOM 子节点之间基于 slot 属性值的**单向、静态、大小写敏感的匹配行为**。它不涉及 JS 逻辑或动态重映射,只在 Shadow DOM 初始化时按规则“抓取”内容并渲染到对应位置。
为什么写了 slot="header" 却没显示?
这是最常遇到的问题,本质是匹配失败且静默丢弃——浏览器既不报错也不警告。
- 外部节点必须是自定义元素的**直系子元素**:
<my-card><h2 slot="header">Hi</h2></my-card>✅;<my-card><div><h2 slot="header">Hi</h2></div></my-card>❌(<h2></h2>是孙节点,不参与分发) -
slot属性值与<slot name="xxx"></slot>的name值必须**完全一致、区分大小写**:<slot name="Header"></slot>不会匹配<h2 slot="header"></h2> - 多个同名
<slot name="item"></slot>会各自收到一份匹配节点副本,不是“分片”,也不是“广播” - 没带
slot属性的节点,只尝试匹配第一个无name的<slot></slot>;后面再多空<slot></slot>也收不到
assignedNodes() 返回空数组怎么办?
这不是 bug,而是时机或配置问题。你不能在 connectedCallback 里立刻调用它。
- 必须监听
slotchange事件:shadowRoot.querySelector('slot').addEventListener('slotchange', () => { ... }),否则内容尚未完成分发 - 默认
assignedNodes()只返回直系分配节点,要拿到所有最终投射内容(含嵌套 slot 中的内容),必须加{ flatten: true } - 如果用了
attachShadow({ mode: 'closed' }),shadowRoot为null,querySelector直接失败 → 日常开发请坚持用'open' -
Uncaught TypeError: Cannot read property 'assignedNodes' of null:说明你忘了先查shadowRoot,或对 Light DOM 里的元素直接调用了该方法
::slotted() 样式为什么不起作用?
它只作用于被 <slot></slot> 投影进来的**顶层元素节点**,且受严格限制。
- 样式规则必须写在 Shadow DOM 内部的
<style></style>里,全局 CSS 或<link>完全无效 - 只匹配插槽“表面”的直接子元素:
<my-card><div><p>hi</p></div></my-card>中,::slotted(div)能命中,::slotted(p)永远不会匹配 - 选择器仅支持简单形式:
::slotted(.btn)✅,::slotted(.btn:hover)❌,::slotted(div p)❌ - 纯文本节点(如
<my-card>hello</my-card>)不是元素节点,任何::slotted()都无法选中 - 外部同名样式优先级更高:
p { color: blue }会覆盖::slotted(p) { color: red }
真正麻烦的从来不是语法本身,而是它不报错、不提示、不警告——内容“消失”时,你得同时检查四件事:自定义元素是否注册、attachShadow() 是否执行成功、Light DOM 子节点结构是否合规、slot 和 name 的字符串是否完全一致。漏掉任何一个,就只剩空白。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











