【Vue3】14-插槽

177 阅读1分钟

插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的 标签。这也是父子间传值的一种方式

1. 默认插槽

子组件中

<template>
    <!-- 插槽占位符,可以有多个,每个的内容都会相同 -->
    <slot></slot>
    <slot></slot>
    <slot></slot>
</template>

父组件中

规范写法:v-slot 表明这里使用 默认插槽,有且只能有一个,并且只能使用在 components or <template> 上
<template>
    <child-slot>
        <template v-slot>
            <div>
                111
            </div>
        </template>
    </child-slot>
</template>

<script setup lang="ts">
import ChildSlot from './components/ChildSlot.vue'
</script>
不规范写法:不写 v-slot,不用 <template>(如果不写 v-slot,用了 <template> 也显示不出来内容)
            那么 <child-slot> 可以包裹任何内容,均能显示出来

2. 具名插槽

子组件中

<!-- 可以看到,默认插槽只能有一个,而具名插槽可以有多个,并且用 name 来命名 -->
<template>
    <slot name="header"></slot>
    <slot></slot>
    <slot name="footer"></slot>
</template>

父组件中

<!-- 父组件中,默认插槽用 v-slot 来标识,具名插槽用 v-slot:name 来标识 -->
<!-- 简写形式:默认插槽用 #default 来标识,具名插槽用 #name 来标识 -->
<template>
    <child-slot>
        <template v-slot:header>
            <div>
                顶部 —— 具名插槽
            </div>
        </template>
        <template v-slot>
            <div>
                中间 —— 默认插槽
            </div>
        </template>
        <template v-slot:footer>
            <div>
                底部 —— 匿名插槽
            </div>
        </template>
    </child-slot>
</template>

3. 动态插槽

子组件中

<template>
    <slot name="dynamic1"></slot>
    <slot name="dynamic2"></slot>
</template>

父组件中

<template>
    <child-slot>
        <!-- 换成变量名,可动态切换插槽名称 -->
        <template #[name]>
            <div>
                动态插槽:{{ name }}
            </div>
        </template>
    </child-slot>
    <button @click="changeSlot">更换插槽</button>
</template>

<script setup lang="ts">
import ChildSlot from './components/ChildSlot.vue'
import { ref } from 'vue'
let name = ref("dynamic1")
const changeSlot = () => {
    name.value = "dynamic2"
}
</script>

4. 作用域插槽(子组件向父组件传值的一种方式)

子组件中

<template>
    <div v-for="(item, index) in objs">
        <!-- 给插槽绑定一些值,可以传到父组件 v-slot 标签中解构出来 -->
        <slot :index="index" :data="item"></slot>
    </div>
</template>

<script setup lang="ts">
import { reactive } from 'vue';
const objs = reactive([
    {
        name: 'zs',
        age: 18
    },
    {
        name: 'ls',
        age: 19
    },
    {
        name: 'ww',
        age: 20
    },
    {
        name: 'll',
        age: 21
    },
])
</script>

父组件中

<template>
    <child-slot>
        <!-- 将子组件插槽中绑定的值解构出来,就可以使用 -->
        <template v-slot="{index, data}">
            <div>
                {{ index }} -- {{ data.name }} -- {{ data.age }}
            </div>
        </template>
    </child-slot>
</template>