Vue.js Slot 内容「消失」全记录:未正确传递的 5 种现场与急救方案
在 Vue 里,Slot 是父组件向子组件动态注入内容的「快递柜」。
然而,很多开发者会遇到:
- 页面空白,子组件里
<slot>
什么也不渲染 - 具名 slot 写了
name="header"
,父组件却传不进去 - 作用域 slot 拿不到子组件数据
<template v-slot>
语法报错v-slot can only be used on components or template tags
本文把最容易踩坑的 5 个 Slot 场景做成「病历卡」,并给出可复制的修复代码,让你 3 分钟定位 + 修复。
一、Slot 基础速查表
类型 | 父组件写法 | 子组件写法 | 常见错误 |
---|---|---|---|
默认 slot | <Child>内容</Child> | <slot /> | 把内容写在自闭合标签内 |
具名 slot | <template #header> | <slot name="header" /> | name 不匹配 |
作用域 slot | <template #item="{ data }"> | <slot :data="item" /> | 解构/声明写错 |
二、5 种翻车现场 & 修复
1️⃣ 内容写在自闭合标签里 —— 直接消失
<!-- ❌ 父组件 -->
<Child content="123" />
<!-- 子组件 Child.vue -->
<slot />
现象:页面空白,123
没出现
原因:自闭合标签内写的内容会被当成 prop 而非 slot
修复:
<!-- ✅ 正确写法 -->
<Child>123</Child>
2️⃣ 具名 slot name 不一致 —— 内容「投递失败」
<!-- ❌ 父组件 -->
<template #head>
<h1>标题</h1>
</template>
<!-- 子组件 -->
<slot name="header" /> <!-- name 不匹配 -->
修复:保持 name 完全一致
<!-- ✅ 父组件 -->
<template #header>
<h1>标题</h1>
</template>
3️⃣ 作用域 slot 解构错误 —— 拿不到数据
<!-- 子组件 -->
<slot :user="user" />
<!-- ❌ 父组件 -->
<template #default="user">
{{ user.name }} <!-- 实际 user 是对象 { user: {...} } -->
</template>
修复:正确解构
<template #default="{ user }">
{{ user.name }}
</template>
或直接使用对象
<template #default="slotProps">
{{ slotProps.user.name }}
</template>
4️⃣ 缩写语法写错 —— 编译直接报错
<!-- ❌ Vue2 旧写法 -->
<template slot="footer" slot-scope="scope">
修复:Vue3 统一用 v-slot
<!-- ✅ -->
<template #footer="{ scope }">
5️⃣ 忘了 <template>
包裹多个根节点内容
<!-- ❌ 父组件 -->
<Child>
<header>头部</header>
<main>主体</main>
</Child>
<!-- 子组件 -->
<div>
<slot name="header" />
<slot />
</div>
现象:第二个 <main>
被塞进默认 slot,布局错乱
修复:用 <template>
明确投递
<Child>
<template #header>
<header>头部</header>
</template>
<template #default>
<main>主体</main>
</template>
</Child>
三、排查 checklist(打印贴屏)
症状 | 检查点 |
---|---|
内容完全不显示 | 是否写在自闭合标签内 |
具名 slot 不生效 | name 是否一致 |
作用域 slot 拿不到数据 | 解构写法是否正确 |
编译报错 | 是否混用 slot /slot-scope |
多个节点 | 是否缺少 <template> 包裹 |
四、一句话总结
Slot 的 90% 问题都源于「投递地址写错」:
自闭合标签、name 不匹配、解构写错、旧语法混用。
把「地址」写对,Slot 永远不会「丢件」。
最后问候亲爱的朋友们,并邀请你们阅读我的全新著作