Vue3 中插槽(Slot)有哪些类型?如何使用?

1. 默认插槽

<!-- 子组件 Card.vue -->
<template>
  <div class="card">
    <slot></slot> <!-- 父组件传入的内容渲染在这里 -->
  </div>
</template>

<!-- 父组件 -->
<Card>
  <p>这是卡片内容</p>
</Card>

2. 具名插槽

<!-- 子组件 Layout.vue -->
<template>
  <div>
    <header><slot name="header"></slot></header>
    <main><slot></slot></main>  <!-- 默认插槽 -->
    <footer><slot name="footer"></slot></footer>
  </div>
</template>

<!-- 父组件 -->
<Layout>
  <template #header>
    <h1>标题</h1>
  </template>

  <p>主要内容</p>  <!-- 默认插槽 -->

  <template #footer>
    <p>底部信息</p>
  </template>
</Layout>

3. 作用域插槽(子传父数据)

<!-- 子组件 List.vue -->
<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      <slot :item="item" :index="index"></slot>
    </li>
  </ul>
</template>

<!-- 父组件 -->
<List :items="users">
  <template #default="{ item, index }">
    <span>{{ index }}. {{ item.name }}</span>
  </template>
</List>

<!-- 或简写 -->
<List :items="users">
  <template="{ item }">
    <span>{{ item.name }}</span>
  </template>
</List>

4. 动态插槽名

<template #[dynamicSlotName]>
  <p>动态插槽内容</p>
</template>

5. 插槽默认内容

<!-- 子组件 -->
<template>
  <slot>默认内容,父组件不传时显示</slot>
</template>

使用 useSlots()

<script setup>
import { useSlots } from 'vue'
const slots = useSlots()

// 判断插槽是否存在
if (slots.header) {
  // 有 header 插槽
}
</script>

实际应用:可复用表格组件

<!-- Table.vue -->
<template>
  <table>
    <thead>
      <tr>
        <th v-for="col in columns" :key="col.key">
          {{ col.title }}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="row in data" :key="row.id">
        <td v-for="col in columns" :key="col.key">
          <!-- 每列都可以自定义渲染 -->
          <slot :name="col.key" :row="row" :value="row[col.key]">
            {{ row[col.key] }}  <!-- 默认显示值 -->
          </slot>
        </td>
      </tr>
    </tbody>
  </table>
</template>

<!-- 使用 -->
<Table :columns="columns" :data="list">
  <template #status="{ row }">
    <span :class="row.status">{{ row.status }}</span>
  </template>
  <template #action="{ row }">
    <button @click="edit(row)">编辑</button>
  </template>
</Table>

同分类其他题目