默认内容失效的根源在于assignednodes()非空判断,哪怕父组件中存在换行或空格也会导致默认内容不显示;具名插槽name必须为静态字面量,动态绑定无效;空template会覆盖默认内容;默认内容不继承样式且无法被::slotted()捕获。

写了默认内容却没显示,先查assignedNodes()是否为空
浏览器判断 slot 是否渲染默认内容,只看 this.shadowRoot.querySelector('slot').assignedNodes() 返回数组长度是不是 0。哪怕父组件里只多了一个换行符或空格,比如 <my-comp>\n </my-comp>,assignedNodes() 就返回非空数组,默认内容立刻失效。
- 调试时别靠眼睛看“页面空不空”,直接在控制台运行
document.querySelector('slot').assignedNodes({ flatten: true }).length - Vue 组件中可在
mounted钩子里用this.$refs.slotRef.assignedNodes()(需给<slot></slot>加ref="slotRef") - Chrome DevTools 中右键 slot 元素 → “Break on” → “attribute modifications”,能抓到 slot 被动态修改的时机
name 必须是静态字面量,动态绑定无效
<slot name="header"></slot> 只匹配 <h1 slot="header"></h1> 或 <template></template>。任何大小写、连字符、空格差异都会导致匹配失败,内容被丢进默认插槽或静默丢弃。
-
<slot :name="headerName"></slot>❌ 不生效——name是 HTML 属性,不是 Vue 响应式绑定目标 - 想实现动态插槽名,只能提前声明多个固定
name的 slot,再用v-if控制显隐 - Vue 中要用
<template v-slot:></template>,但子组件仍得用静态<slot name="xxx"></slot>
具名插槽的空 <template></template> 会覆盖默认内容
父组件写了 <template></template>,哪怕里面啥都没有,Vue 也认为“已提供内容”,于是跳过子组件中 <slot name="icon"><i class="icon-default"></i></slot> 的默认内容。
- 真正“没传”的唯一方式是:父组件里彻底不出现
#icon或v-slot:icon - 如果业务上需要“内容为空时仍 fallback”,得在子组件里手动判断:
slots.icon?.() || <i class="icon-default"></i>(Composition API) - 默认内容里不能访问作用域变量,比如
<slot name="item" :item="item">{{ item?.name }}</slot>❌ 会报undefined
默认内容不继承样式,::slotted() 拿不到它
<slot>Loading</slot> 渲染出来的文本节点属于 slot 容器内部,不是通过分发进来的节点,因此不受 ::slotted(*) 影响,也不自动继承父级字体、颜色等样式。
- 必须显式加类或内联样式:
<slot><span style="color: #666">Loading</span></slot> - 全局 CSS 规则能命中它,但要注意选择器权重和作用域限制(尤其
<style scoped></style>) - Web Components 中更明显——默认内容在 shadow DOM 内,外部样式默认无法穿透
template、一个大小写错位的 name,都足以让默认内容彻底消失。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











