文章目录
- Vue3 组件之插槽
- 概述
- 默认插槽
- 具名插槽
- 默认内容插槽
- 没有提供内容
- 有提供内容
- 作用域插槽
- 简单使用
- 使用解构形式
Vue3 组件之插槽
概述
插槽专门用于父组件向子组件传递标签结构。在使用时,一般会在子组件中通过slot来声明占位,在父组件中,通过子组件的标签体向子组件传递标签结构。
插槽主要分3种:
- 默认插槽。
- 具名插槽。
- 默认内容插槽。
- 作用域插槽。
默认插槽
仅支持使用单个插槽。
主要分2步:
- 在组件中使用
<slot>
标签表示插槽出口。 - 在父组件中提供内容。
定义插槽组件 MySlot.vue:
<template>
<h2>默认插槽</h2>
<!--插槽出口-->
<slot></slot>
</template>
使用插槽:
<MySlot>
<!--插槽内容-->
<button>按钮</button>
<br>
<input type="text" placeholder="请输入123">
</MySlot>
以上是默认简写形式,完整写法如下:
MySlot.vue:
<template>
<h2>默认插槽</h2>
<!--插槽出口-->
<slot name="default"></slot>
</template>
使用插槽:
<MySlot v-slot:default>
<!--插槽内容-->
<button>按钮</button>
<br>
<input type="text" placeholder="请输入123">
</MySlot>
效果:
具名插槽
主要分2步:
- 在组件中给
<slot>
指定插槽名称,如```。 - 在父组件中通过
<template>
使用具名插槽,如<template v-slot:title></template>
。
定义插槽组件 MyNamedSlot.vue:
<template>
<h2>具名插槽</h2>
<slot name="title"></slot>
-----
<slot name="content"></slot>
</template>
使用插槽:
<MyNamedSlot>
<template v-slot:title>
<h3>标题</h3>
</template>
<template v-slot:content>
<p>这是一些内容</p>
</template>
</MyNamedSlot>
效果:
默认内容插槽
在外部没有提供任何内容的情况下,可以为插槽指定默认内容。
定义默认内容插槽 MyDefault.vue:
<template>
<h2>默认内容插槽</h2>
<slot name="title">
<h3>默认标题</h3>
</slot>
<slot name="content">
<p>默认内容</p>
</slot>
</template>
没有提供内容
使用插槽:
<MyDefaultSlot>
</MyDefaultSlot>
效果:
有提供内容
使用插槽:
<MyDefaultSlot>
<template v-slot:title>
<h3>我的标题</h3>
</template>
<template v-slot:content>
<h3>我的内容</h3>
</template>
</MyDefaultSlot>
效果:
作用域插槽
在某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点,我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽。
主要分3步:
- 父组件给插槽提供数据。
- 子组件的插槽回传数据。
- 父组件再处理回传数据。
简单使用
定义插槽组件 MyListSlot.vue:
<script setup>
defineProps(['list']);
</script>
<template>
<h2>作用域插槽</h2>
<ul>
<li v-for="({name,age},index) in list" :key="item">
<slot :uname="name" :age="age" :index="index"></slot>
</li>
</ul>
</template>
使用作用域插槽:
<script setup>
import MyListSlot from "./components/MyListSlot.vue";
import {ref} from "vue";
const userList = ref([{name: "小明", age: 18}, {name: "小白", age: 28}, {name: "小黑", age: 38}]);
</script>
<template>
<MyListSlot :list="userList">
<template v-slot="slotProps">
<p>index: {{ slotProps.index }} ,姓名:{{ slotProps.uname }} ,年龄:{{ slotProps.age }}</p>
</template>
</MyListSlot>
</template>
效果:
使用解构形式
定义插槽组件 MyListSlot.vue:
<script setup>
defineProps(['list']);
</script>
<template>
<h2>作用域插槽</h2>
<ul>
<li v-for="(item,index) in list">
<slot :user="item" :index="index"></slot>
</li>
</ul>
</template>
使用插槽:
<MyListSlot :list="userList">
<template v-slot="{user,index}">
<p>index: {{ index }} ,姓名:{{ user.name }} ,年龄:{{ user.age }}</p>
</template>
</MyListSlot>