文章

Vue3基础——插槽Slots

开始

使用插槽可以实现动态的模板内容

父模板中的插槽内容可以访问到父组件的数据作用域,但不能访问到子组件的数据作用域

插槽图示

默认插槽

不具有name属性的插槽为默认插槽

父组件基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script setup lang="ts">
import {ref} from 'vue';
import Inner from "@/components/Inner.vue";
let value1 = ref('value1');
</script>

<template>
  <div>
    <Inner>
      <!--该部分内容会填充到插槽中-->
      <span>{ {value1} }</span>
    </Inner>
  </div>
</template>

子组件基本使用

1
2
3
4
5
6
7
8
9
<script setup lang="ts">
</script>

<template>
  <div>
    <!--slot标签定义默认插槽-->
    <slot></slot>
  </div>
</template>

slot标签中的模板内容为默认填充内容,当父组件未定义插槽内容时,使用默认内容填充

1
2
3
4
5
6
7
8
9
<!--子组件-->
<template>
  <div>
    <slot>默认内容</slot>
  </div>
</template>

<!--父组件-->
<Inner></Inner>

具名插槽

可以为slot设置名称,指明插槽内容填充的slot

  • slot标签使用name属性设置名称
  • 使用v-slot指令指明填充的slot,该指令可用于组件标签或template标签上,可简写为#

当同时使用具名插槽和默认插槽时,可使用显式默认插槽或隐式默认插槽

  • 显式默认插槽:使用v-slot:default指明填充到默认插槽
  • 隐式默认插槽:组件标签中所有的直接非template标签将作为默认插槽内容

基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!--子组件-->
<template>
  <div>
    <slot name="header"></slot>
    <slot name="content"></slot>
  </div>
</template>

<!--父组件-->
<template>
  <div>
    <Inner>
      <template v-slot:header>
        <span>这是header</span>
      </template>
      <template #content>
        <div>这是content</div>
      </template>
    </Inner>
  </div>
</template>

作用域插槽

使用作用域插槽可向插槽内容提供子组件的数据

  • 在子组件的slot标签中传递参数
  • 在父组件中接收参数

基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--子组件-->
<div>
  <!--通过v-bind传递参数-->
  <slot :text="greetingMessage" :count="1"></slot>
</div>

<!--父组件-->
<!--使用一个对象接收参数-->
<MyComponent v-slot="slotProps">
  { { slotProps.text } } { { slotProps.count } }
</MyComponent>

<!--
接收参数时可以使用解构
<MyComponent v-slot="{ text, count }">
  { { text } } { { count } }
</MyComponent>
-->

在同时使用默认插槽和具名插槽时,作用域插槽必须显式指明默认插槽

1
2
3
4
5
6
7
8
9
10
11
12
<template>
  <MyComponent>
    <!-- 使用显式的默认插槽 -->
    <template #default="{ message }">
      <p>{ { message } }</p>
    </template>

    <template #footer>
      <p>Here's some contact info</p>
    </template>
  </MyComponent>
</template>

其他特性

条件插槽

$slots对象用于获取父组件传入所有插槽填充内容,配合v-if可实现条件渲染slot标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
  <div class="card">
    <div v-if="$slots.header" class="card-header">
      <slot name="header" />
    </div>
    
    <div v-if="$slots.default" class="card-content">
      <slot />
    </div>
    
    <div v-if="$slots.footer" class="card-footer">
      <slot name="footer" />
    </div>
  </div>
</template>

动态插槽名

v-slot指令上可使用动态插槽名

1
2
3
4
5
6
7
8
9
10
<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>

  <!-- 缩写为 -->
  <template #[dynamicSlotName]>
    ...
  </template>
</base-layout>
本文由作者按照 CC BY 4.0 进行授权