slot name属性必须是静态小写连字符字符串,浏览器执行纯字符串精确比对,大小写、空格、连字符全敏感;内容须为自定义元素的直系子节点,未声明插槽则静默丢弃,且name不支持动态绑定或后续修改。

slot name 属性必须是静态小写连字符字符串
浏览器对 name 属性执行纯字符串精确比对,不忽略大小写、空格或连字符。比如 <slot name="user-avatar"></slot> 只匹配 <h2 slot="user-avatar"></h2>,而以下全部失败:
-
<h2 slot="User-Avatar"></h2>(首字母大写) -
<h2 slot="user_avatar"></h2>(下划线代替连字符) -
<h2 slot="user-avatar "></h2>(末尾空格) -
<h2 slot="useravatar"></h2>(漏掉连字符)
Web Components 规范明确要求 name 值只能是小写 ASCII 字符 + 连字符,不支持数字开头、特殊符号或 Unicode 字符。
内容必须是自定义元素的直系子节点才能被分发
slot 分发只检查 Light DOM 中自定义元素的**第一层子节点**,嵌套一层就失效。例如:
<my-card><header slot="header">标题</header><div><p slot="body">段落</p></div> <!-- ❌ 不会被分发到 body 插槽 --> </my-card>
上面的 <p slot="body"></p> 因为被 <div> 包裹,不再是 <code><my-card></my-card> 的直接子节点,所以不会进入 <slot name="body"></slot>。修复方式只有两个:
- 把
<p slot="body"></p>提到外层,成为<my-card></my-card>的直接子节点 - 在
<div> 上加 <code>slot="body",让整个 div 被投射过去(再由内部样式或子组件处理内容)没声明的 slot="xxx" 内容会静默丢弃,不报错也不 fallback
如果父组件写了
<h3 slot="footer">版权</h3>,但子组件 Shadow DOM 里没有<slot name="footer"></slot>,那这行 HTML 就完全不会渲染——既不显示,也不进默认插槽,控制台也无提示。更隐蔽的问题是:子组件只写了
<slot name="footer">默认版权</slot>,但父组件传了空节点<div slot="footer"></div>,这时 fallback 文本(“默认版权”)也不会出现,因为已有匹配节点,哪怕它是空的。调试时可直接查
slotElement.assignedNodes()返回是否为空数组,这是判断是否匹配成功的最可靠方式。name 属性不支持动态绑定或 JS 修改
name是纯静态 HTML 属性,不能用v-bind:name、:name、模板字符串name="${foo}"或setAttribute('name', 'xxx')动态设置。原因在于 slot 分发发生在元素连接(
connectedCallback)时的一次性解析过程,后续改name不触发重分配。常见误写:-
<slot :name="currentSlot"></slot>→ 实际生成的是name="currentSlot"字面量 -
<slot name="{{slotName}}"></slot>→ 浏览器当普通字符串,不解析表达式 -
slotEl.setAttribute('name', 'new-name')→ 对已挂载的 slot 无效
真要实现条件切换,得预先写好多个固定
<slot name="a"></slot>和<slot name="b"></slot>,再配合 CSSdisplay: none或 JS 控制显隐。最容易被忽略的其实是 slot 分发的“一次性”本质:它不监听后续 DOM 变化,也不响应属性更新。一旦内容被分配,除非手动调用
assignSlots()(仅 Chrome 支持且非标准),否则不会重新计算。写 Web Components 时,这点必须从设计阶段就约束住结构和命名。 -











