Vue 3 插槽(Slot)详解

🧩 一、什么是插槽(Slot)

插槽(Slot) 是 Vue 中的一个非常强大的特性,用于在 组件之间传递结构化内容

简而言之:

插槽就是 "占位符",父组件可以在这个占位符中插入任意模板内容。


🧱 二、插槽的三种类型

Vue 3 中主要有三类插槽:

  1. 默认插槽(Default Slot)

  2. 具名插槽(Named Slot)

  3. 作用域插槽(Scoped Slot)


🧭 三、默认插槽(Default Slot)

🔹 子组件定义插槽

html 复制代码
<!-- Child.vue -->
<template>
  <div class="child">
    <h3>我是子组件</h3>
    <slot></slot> <!-- 插槽占位 -->
  </div>
</template>

🔹 父组件传入内容

html 复制代码
<!-- Parent.vue -->
<template>
  <Child>
    <p>这是插入到默认插槽的内容。</p>
  </Child>
</template>

🔹 渲染结果

html 复制代码
<div class="child">
  <h3>我是子组件</h3>
  <p>这是插入到默认插槽的内容。</p>
</div>

如果父组件没有传入任何内容,Vue 会使用 默认内容

html 复制代码
<slot>这里是默认内容</slot>

🏷️ 四、具名插槽(Named Slot)

当一个组件有多个插槽时,就需要用名字来区分。

🔹 子组件定义

html 复制代码
<!-- Child.vue -->
<template>
  <header>
    <slot name="header">默认头部</slot>
  </header>
  <main>
    <slot>默认主体</slot>
  </main>
  <footer>
    <slot name="footer">默认底部</slot>
  </footer>
</template>

🔹 父组件传入

html 复制代码
<template>
  <LayoutComponent>
    <!-- Vue 3 语法:使用 v-slot 指令 -->
    <template v-slot:header>
      <h1>网站标题</h1>
      <nav>导航菜单</nav>
    </template>
    
    <template v-slot:content>
      <article>
        <h2>文章标题</h2>
        <p>文章内容...</p>
      </article>
    </template>
    
    <template v-slot:sidebar>
      <div class="sidebar">
        <h3>侧边栏</h3>
        <ul>
          <li>链接1</li>
          <li>链接2</li>
        </ul>
      </div>
    </template>
    
    <template v-slot:footer>
      <p>版权信息 © 2023</p>
    </template>
  </LayoutComponent>
</template>

💡 注意:

  • #headerv-slot:header 的语法糖。

  • 默认插槽用 #default 或直接写内容。


🧮 五、作用域插槽(Scoped Slot)

作用域插槽允许子组件 向父组件传递数据

🔹 子组件提供数据

html 复制代码
<!-- Child.vue -->
<template>
  <ul>
    <slot :items="list"></slot>
  </ul>
</template>

<script setup>
const list = ['苹果', '香蕉', '橘子']
</script>

🔹 父组件使用插槽并接收数据

html 复制代码
<!-- Parent.vue -->
<template>
  <Child v-slot="{ items }">
    <li v-for="(item, i) in items" :key="i">{{ i + 1 }} - {{ item }}</li>
  </Child>
</template>

渲染结果:

html 复制代码
<ul>
  <li>1 - 苹果</li>
  <li>2 - 香蕉</li>
  <li>3 - 橘子</li>
</ul>

💡 说明

  • 子组件通过 slot 标签上的属性向父组件 暴露数据

  • 父组件使用 v-slot="{ ... }" 解构这些数据;

  • 这就是"作用域插槽":父组件可以访问子组件提供的"插槽上下文"。


🧱 六、v-slot 完整语法总结

语法形式 用法说明
<template v-slot:header> 具名插槽
<template #header> 具名插槽(语法糖)
<template v-slot:default> 默认插槽
<template #default> 默认插槽(语法糖)
<Child v-slot="{ data }"> 作用域插槽
<Child #default="{ data }"> 作用域插槽语法糖

🧠 七、插槽底层原理(简述)

Vue 的插槽在编译阶段会被转换成渲染函数(render function)的一部分:

  • 子组件模板中的 <slot> 会生成一个 slot 函数调用

  • 父组件传入的 <template v-slot> 会被编译为一个 函数

  • 渲染时,Vue 会把父组件提供的函数传递给子组件,子组件在执行时调用它,形成一种 内容分发机制

所以插槽本质上是:

"通过函数传递模板内容" 的机制。


⚙️ 八、综合示例

html 复制代码
<!-- Card.vue -->
<template>
  <div class="card">
    <header><slot name="header">默认标题</slot></header>
    <main><slot :info="info"></slot></main>
    <footer><slot name="footer">默认页脚</slot></footer>
  </div>
</template>

<script setup>
const info = { author: 'smatter er', date: '2025-10-30' }
</script>
html 复制代码
<!-- App.vue -->
<template>
  <Card>
    <template #header>
      <h2>文章标题</h2>
    </template>

    <template #default="{ info }">
      <p>作者:{{ info.author }},日期:{{ info.date }}</p>
    </template>

    <template #footer>
      <button>阅读全文</button>
    </template>
  </Card>
</template>

渲染结果:

html 复制代码
<div class="card">
  <header><h2>文章标题</h2></header>
  <main><p>作者:smatter er,日期:2025-10-30</p></main>
  <footer><button>阅读全文</button></footer>
</div>

🧩 九、插槽的使用建议

适用场景:

  • 通用组件(如卡片、弹窗、表格);

  • 灵活布局(header、footer、sidebar);

  • 组件内动态内容插入。

⚠️ 注意事项:

  • 插槽内容在父组件作用域中编译;

  • 子组件只能通过作用域插槽提供数据;

  • 避免滥用插槽导致组件复杂化。

相关推荐
袁煦丞3 小时前
本地AI绘画神器+全局访问——Stable Diffusion WebUI 成功突破:cpolar内网穿透实验室第462个成功挑战
前端·程序员·远程工作
一枚前端小能手3 小时前
🏗️ JavaScript类深度解析 - 从构造函数到现代特性的完整指南
前端·javascript
袁煦丞3 小时前
家用NAS+云盘自由NanoPi R4S+iStoreOS:cpolar内网穿透实验室第460个成功挑战
前端·程序员·远程工作
浏览器API调用工程师_Taylor4 小时前
日报自动化实战:告别手动复制粘贴
前端·javascript·node.js
晴殇i4 小时前
JavaScript还能这样写?!ES2025新语法让代码优雅到极致
前端·javascript·程序员
浏览器API调用工程师_Taylor4 小时前
我是如何将手动的日报自动化的☺️☺️☺️
前端·javascript·爬虫
东哥很忙XH4 小时前
flutter开发的音乐搜索app
android·javascript·flutter
前端Hardy5 小时前
HTML&CSS&JS:抖音爆火的满屏“关心弹幕”酷炫卡片,已经帮你打包好了,快来体验吧!
前端·javascript·css
江城开朗的豌豆5 小时前
我的Vue项目胖成球了!用Webpack给它狠狠瘦个身
前端·javascript