vue插槽默认内容不显示是因为换行、空格等空白符会被视为真实内容,导致插槽跳过默认渲染;需用v-if="$slots.default"显式判断并配合v-else实现可靠fallback。

为什么<slot></slot>默认内容不显示
不是你写错了,而是 Vue 已经“看到内容”了——哪怕一个空格、一次换行、一条注释,都会让 <slot></slot> 认为“父组件传了东西”,从而跳过默认内容渲染。
常见现象:<mycard></mycard> 显示默认文案;但 <mycard>\n</mycard> 或 <mycard></mycard> 就完全空白。这是因为换行符和空格在 DOM 中是真实存在的文本节点,Vue 会把它们当作插槽内容分配进去。
- 父组件中用
<template v-slot:default></template>显式声明空插槽,也会屏蔽默认内容 -
<mycard><p></p></mycard>:一个空<p></p>也算内容,后备不触发 - 子组件外层加了
v-if="show"包裹<slot></slot>,那即使没传内容,只要show为 false,默认内容也压根不会求值
v-if="$slots.default" 是最稳的 fallback 控制方式
Vue 不会自动帮你做“有内容才渲染传入内容,否则退回到默认文案”这种逻辑——它只做“替换”,不做“条件回退”。所以真要保底,得手动判断。
创建并管理 Docker 沙箱虚拟机环境以安全执行代理。适用于运行不受信任代码、探索包或隔离代理工作负载。支持 Claude、Codex、Copilot、Gemini 和 Kiro 代理,并提供网络代理控制。
子组件模板里别只靠 <slot>默认文案</slot>,而要用显式条件:
<div class="card"> <slot v-if="$slots.default"></slot><div v-else>这里是一张空卡片,请传入内容</div> </div>
-
$slots.default是函数,存在即表示父组件提供了默认插槽内容(哪怕只传了个空格) -
v-else块里的内容才是你真正可控的 fallback,不受空格/换行干扰 - 这个模式对具名插槽同样适用:
v-if="$slots.header"+v-else写默认头部 - 注意:setup 中使用
slots对象时,必须写成slots.default?.()才能安全调用,否则会报错
作用域插槽的默认内容不能访问作用域变量
比如子组件写了 <slot v-bind:user="userInfo">暂无用户信息</slot>,父组件没传内容时,“暂无用户信息”能显示;但如果你在里面写 {{ user.name }},它要么报错,要么渲染为空——因为作用域变量只在父组件传入插槽内容并执行时才绑定。
- 作用域插槽的默认内容只能是静态文本或基于全局状态的表达式(如
v-if="isLoggedIn") - 若需动态 fallback(比如根据
userInfo状态显示不同文案),应在子组件内用v-if+$slots.default判断,再配合普通元素渲染,而不是塞进<slot></slot>标签内部 - 不要试图在默认内容里解构作用域参数,
<slot v-bind="data">{{ data?.name }}</slot>是无效的
uni-app 和小程序平台的 slot name 兼容陷阱
在微信小程序或 uni-app 的非 H5 平台,具名插槽的 name 值必须全小写+中划线,比如 user-info 可以,userInfo 或 user_info 会直接失效——此时即使你写了 <slot name="userInfo">默认</slot>,父组件用 <template></template> 也匹配不上,导致默认内容意外显示(你以为被覆盖了,其实根本没匹配成功)。
- 统一用
v-slot:user-info写法,避免#userInfo简写在小程序端不稳定 - App 和 H5 支持驼峰,但微信小程序只认 kebab-case,跨平台组件务必按最低标准约束
- NVue 渲染模式下不支持具名 slot,只认默认插槽,此时所有
name属性都会被忽略
真正难的不是写默认文案,而是理解 Vue 插槽的“分配判定”发生在编译期——它看的是父组件模板的 AST 节点结构,不是运行时的字符串空不空。一个看不见的换行,就足以让保底逻辑彻底失效。










