vue3中slot,template #名称 的详细说明和具体示例

在 Vue3 中,slot(插槽)是组件间传递内容的核心方式,template #名称 是 template v-slot:名称 的语法糖,用于绑定具名插槽。下面我会从基础到进阶,详细讲解用法并给出可直接运行的示例。

一、核心概念先理清

  1. 插槽的作用:让组件的部分内容由使用组件的父组件自定义,实现组件内容的灵活复用。
  2. # 语法糖 :#xxx 等价于 v-slot:xxx,只能用在 <template> 标签上(或组件标签本身,仅限默认插槽)。
  3. 分类 :
    • 具名插槽:有明确名称的插槽(如 #header、#content),用于组件内多位置自定义内容。
    • 默认插槽:无名称的插槽(#default,可省略),组件内未命名的插槽位置。
    • 作用域插槽:插槽可以接收子组件传递的数据(核心:子传父,父组件自定义渲染逻辑)。

二、具体用法 + 完整示例

1. 基础:具名插槽(template #名称 核心用法)

步骤1:定义带具名插槽的子组件(MySlot.vue)

子组件通过 <slot name="xxx"> 定义插槽位置,name 对应父组件的 #xxx。

vue 复制代码
<!-- MySlot.vue -->
<template>
  <div class="slot-container">
    <!-- 头部插槽 -->
    <div class="header">
      <slot name="header">默认头部内容(父组件没传则显示这个)</slot>
    </div>
    
    <!-- 内容插槽 -->
    <div class="content">
      <slot name="content">默认内容</slot>
    </div>
    
    <!-- 底部插槽(默认插槽,省略name) -->
    <div class="footer">
      <slot>默认底部内容</slot>
    </div>
  </div>
</template>

<style scoped>
.slot-container {
  border: 1px solid #ccc;
  padding: 20px;
  width: 400px;
  margin: 20px auto;
}
.header { border-bottom: 1px solid #eee; padding-bottom: 10px; }
.content { padding: 10px 0; }
.footer { border-top: 1px solid #eee; padding-top: 10px; color: #666; }
</style>

步骤2:父组件使用 template #名称 传递内容

父组件通过 <template #插槽名> 给对应插槽传递自定义内容:

vue 复制代码
<!-- 父组件 App.vue -->
<template>
  <div>
    <h2>具名插槽示例</h2>
    <MySlot>
      <!-- 绑定header插槽:#header 等价于 v-slot:header -->
      <template #header>
        <h3>自定义的头部标题</h3>
      </template>

      <!-- 绑定content插槽 -->
      <template #content>
        <p>这是自定义的内容区域,可放任意HTML/组件</p>
        <button>自定义按钮</button>
      </template>

      <!-- 默认插槽:#default 可省略,直接写内容 -->
      <template #default>
        <p>自定义的底部内容</p>
      </template>
      <!-- 简化写法:默认插槽无需template,直接写内容 -->
      <!-- <p>自定义的底部内容</p> -->
    </MySlot>
  </div>
</template>

<script setup>
import MySlot from './components/MySlot.vue';
</script>

效果:

  • 头部显示「自定义的头部标题」(替换了子组件的默认头部);
  • 内容区显示自定义的文字+按钮;
  • 底部显示「自定义的底部内容」。
2. 进阶:作用域插槽(带参数的 template #名称)

作用域插槽的核心是子组件向插槽传递数据 ,父组件通过 #名称="参数" 接收,再自定义渲染逻辑。

步骤1:子组件定义带数据的插槽(MyScopeSlot.vue)

通过 slot 标签的属性传递数据(如 :list="list"):

vue 复制代码
<!-- MyScopeSlot.vue -->
<template>
  <div class="scope-slot">
    <h4>子组件的列表数据</h4>
    <!-- 具名作用域插槽:向父组件传递list数据 -->
    <slot name="list" :list="list" :title="'用户列表'">
      <!-- 默认渲染逻辑(父组件没自定义则显示) -->
      <ul>
        <li v-for="item in list" :key="item.id">{{ item.name }}</li>
      </ul>
    </slot>
  </div>
</template>

<script setup>
// 子组件的数据源
const list = [
  { id: 1, name: '张三', age: 20 },
  { id: 2, name: '李四', age: 22 },
  { id: 3, name: '王五', age: 24 },
];
</script>

步骤2:父组件接收并自定义渲染(App.vue)

通过 #list="slotProps" 接收子组件传递的参数(slotProps 是自定义名称,也可解构):

vue 复制代码
<!-- 父组件 App.vue -->
<template>
  <div>
    <h2>作用域插槽示例</h2>
    <MyScopeSlot>
      <!-- 方式1:完整接收参数 -->
      <!-- <template #list="slotProps">
        <div>
          <h5>{{ slotProps.title }}</h5>
          <table border="1">
            <tr v-for="item in slotProps.list" :key="item.id">
              <td>{{ item.id }}</td>
              <td>{{ item.name }}</td>
              <td>{{ item.age }}</td>
            </tr>
          </table>
        </div>
      </template> -->

      <!-- 方式2:解构参数(推荐,更简洁) -->
      <template #list="{ list, title }">
        <div>
          <h5>{{ title }}</h5>
          <table border="1" cellpadding="5">
            <tr>
              <th>ID</th>
              <th>姓名</th>
              <th>年龄</th>
            </tr>
            <tr v-for="item in list" :key="item.id">
              <td>{{ item.id }}</td>
              <td>{{ item.name }}</td>
              <td>{{ item.age }}</td>
            </tr>
          </table>
        </div>
      </template>
    </MyScopeSlot>
  </div>
</template>

<script setup>
import MyScopeSlot from './components/MyScopeSlot.vue';
</script>

效果 :

父组件接收到子组件的 list 和 title,并将原本的列表渲染成了表格(替换了子组件的默认列表渲染)。

3. 特殊场景:默认插槽的语法糖简化

如果只有默认插槽,可直接在组件标签上用 #default(或省略),甚至直接绑定参数:

vue 复制代码
<!-- 简化写法:默认插槽 -->
<MyScopeSlot #default="{ list }">
  <ul>
    <li v-for="item in list" :key="item.id">{{ item.name }} - {{ item.age }}岁</li>
  </ul>
</MyScopeSlot>

<!-- 更简化:直接写在组件标签上(仅限默认插槽) -->
<MyScopeSlot v-slot="{ list }">
  <p>默认插槽简化写法:{{ list[0].name }}</p>
</MyScopeSlot>

三、注意事项

  1. # 是 v-slot: 的语法糖,只能用在 <template> 标签上(默认插槽可例外,写在组件标签上);
  2. 具名插槽必须匹配子组件 slot 的 name 属性,否则会渲染默认内容;
  3. 作用域插槽的参数可以解构,也可以重命名(如 #list="{ list: userList }");
  4. Vue3 中 slot 和 slot-scope 已废弃,统一使用 v-slot(或 #)。

总结

  1. template #名称 是 template v-slot:名称 的语法糖,用于绑定具名插槽,核心是父组件向子组件指定位置传递自定义内容;
  2. 作用域插槽通过 #名称="参数" 接收子组件传递的数据,实现「子传父+父自定义渲染」;
  3. 默认插槽可省略 #default,直接写内容,作用域插槽的参数支持解构,简化代码。

通过插槽(尤其是 # 语法糖),你可以灵活定制组件的内容,是 Vue 组件封装中最常用的技巧之一。

相关推荐
迷途小羔羊21 分钟前
环境搭建
前端·javascript·后端
夕阳_醉了27 分钟前
让 AI 回答“打字般”浮现:用 Vue 3 + DeepSeek 实现流式聊天
前端·vue.js·人工智能
酷炫码神1 小时前
Day 9|Vue Router:把单页后台拆成能跳转的多页面
前端·javascript·vue.js
Sapphire~1 小时前
odoo-095 视图的重写规则(全部重写还是部分改写)
开发语言·javascript·ecmascript
_菜鸟果果17 小时前
高德地图 JS API 2.0 在国产 Linux/ARM 电脑上渲染失败 的排查与解决
linux·开发语言·javascript
Java后端的Ai之路17 小时前
前端技术Vue-09-webpack-vuejs-实战
前端·vue.js·webpack
迷途小羔羊18 小时前
项目概述
java·javascript·后端
迷迭绿18 小时前
Cesium 轨迹回放播放器
前端·javascript·cesium
tryCbest19 小时前
Vue3——第 7 篇:组件基础——从注册到使用的完整流程
前端·javascript·vue.js