具名插槽匹配严格区分大小写,name属性必须完全一致;不支持动态绑定,仅接受静态字面量;未声明插槽则内容静默丢弃。

slot name 属性大小写必须完全一致
具名插槽匹配失败,八成是因为 name 值大小写不匹配。浏览器对 slot 元素的 name 属性执行严格字符串比对,不忽略大小写、不自动转换、不 fallback。
比如:<slot name="Header"></slot> 只接收 <p slot="Header">...</p>;而 <p slot="header">...</p> 会被丢进默认插槽(如果存在),或直接静默丢弃(如果没定义默认插槽)。
- 所有主流浏览器(Chrome/Firefox/Safari/Edge)行为完全一致,这不是 bug,是 HTML 规范强制要求
- Vue/React 等框架若底层用原生 Shadow DOM(如自定义元素 +
attachShadow),同样受此约束 - 调试时可调用
slotElement.assignedNodes()检查返回是否为空,快速确认是否匹配失败
name 属性不支持动态绑定
name 是纯静态 HTML 属性,不能写成 <slot :name="headerName"></slot> 或 <slot name="{{ headerName }}"></slot>。这类写法在解析阶段就当作字面量字符串处理,不会求值。
例如 Vue 模板中未用 v-bind:name,实际生成的 DOM 就是 <slot name="headerName"></slot> —— 注意引号里真的是 “headerName” 这五个字母,不是变量内容。
立即学习“前端免费学习笔记(深入)”;
- 真正有效的只有编译/运行时已确定的字面量:如
<slot name="header"></slot>、<slot name="user-avatar"></slot> - 想实现“动态插槽名”,得靠 JS 手动控制:比如根据条件渲染多个固定
<slot name="a"></slot>/<slot name="b"></slot>,再配合v-if切换显隐 - 在 HTML 源码里写
name="${slotName}"完全无效,只在 JS 字符串拼接或服务端模板中起作用
具名插槽与默认插槽共存规则
一个组件内可以同时有多个具名插槽和一个(且仅一个)无 name 的默认插槽。分发逻辑很明确:内容按 slot 属性值精确匹配具名插槽;不匹配的,才进默认插槽。
比如子组件含 <slot name="header"></slot>、<slot></slot>、<slot name="footer"></slot>,那么:
-
<div slot="header">...→ 进第一个插槽 -
<div slot="footer">...→ 进第三个插槽 -
<div>...(无 slot 属性)或<div slot="unknown">...→ 全部进中间那个默认插槽 - 重复声明同名插槽(如两个
<slot name="header"></slot>)允许,但内容只被第一个捕获,后续同名插槽保持空
没声明任何插槽?所有传入内容都会被丢弃,DOM 中不可见也不可访问 —— 这点容易被忽略,尤其在封装初期忘记加 <slot></slot> 时。
未匹配的 slot="xxx" 内容不会报错,只会静默丢失
父组件写了 <p slot="sidebar">...,但子组件根本没定义 <slot name="sidebar"></slot>,也不会警告或报错。内容直接消失,连进默认插槽的机会都没有。
这种静默行为让问题难定位,尤其在组件迭代过程中删掉某个插槽却忘了同步清理父级用法时。
- 可在子组件监听
slotchange事件,检查event.target.assignedNodes().length === 0来发现“空插槽” - 更稳妥的做法是:组件文档明确列出支持的
name值,并在开发环境用console.warn提示未知slot属性(需手动解析this.childNodes或lightDOM) - 注意:即使插槽元素被设为
display: none,只要它还在 DOM 中,后续改name也不会触发重分发 —— 分发只发生在初始插入时

















