插槽内容不显示,主因是v-if误加在标签上;正确做法是用外层容器包裹并绑定v-if,或在作用域插槽中使用安全访问语法。

插槽内容不显示,八成是 v-if 错放位置了。Vue 的 slot 本质是“内容出口”,不是“容器”,v-if 直接加在 <slot></slot> 标签上,会把整个出口干掉——父组件传的内容根本进不来,自然什么也看不到。
别把 v-if 写在 标签上
这是最常见也最容易踩的坑。比如子组件里这样写:
-
<slot v-if="showHeader"></slot>→ 错误!showHeader为 false 时,<slot></slot>节点被完全移除,父组件传的 header 插槽内容压根不会被编译、也不会传递进来。 - 正确做法:用一个外层容器包裹具名插槽,并把
v-if放在容器上:<div v-if="showHeader"><slot name="header"></slot></div>。这样插槽始终存在,只是容器按需渲染。
uni-app 小程序里更敏感
微信小程序对 slot 渲染机制更严格,v-if 和 v-slot 同时出现在同一元素上,容易直接失效(尤其在 H5 正常、小程序白屏时)。常见表现:
-
<template v-slot:header v-if="show">…</template>→ 小程序可能忽略v-if或完全不渲染 - 推荐写法:先判断条件,再决定是否嵌套
v-slot块:<template v-if="show"><template v-slot:header>…</template></template> - 实在不行,就把
v-if下沉到插槽内部标签里,比如<u-icon v-if="isLink" name="arrow-right"></u-icon>
el-table / uview 等组件中要防缓存干扰
像 el-table-column 或 u-collapse-item 这类封装较深的组件,内部会对列/插槽做预编译或实例缓存。一旦你用 v-if 控制插槽内容,容易触发 DOM 复用异常:
- 表头图标不更新、操作列文字错乱、列宽崩塌
- 控制台报
cannot read property 'renderHeader' of undefined - 解决关键:给
el-table或el-table-column加唯一:key,比如:key="tableKey"(每次数据变更时更新),强制重新解析插槽结构 - 或者用
<div> 包裹插槽内容,避免 <code>v-if直接作用于 slot 出口作用域插槽里注意数据安全
用
<slot name="item" :row="row"></slot>时,如果在子组件中这样写:<slot name="item" v-if="row.id"></slot>,row可能还没传入就执行判断,导致报错。- 改用安全访问:
v-if="row?.id"(Vue 3)或v-if="row && row.id"(Vue 2) - 或提前设默认值:
props: { row: { type: Object, default: () => ({}) } } - 动态插槽名也要小心:
<slot :name="customName" v-if="hasCustom"></slot>✅;<slot :name="hasCustom ? 'custom' : null"></slot>❌(null不合法)
- 改用安全访问:










