Vue 实现了一套内容分发的 API,将
元素作为承载分发内容的出口,使用插槽使得vue组件的设计更加灵活。
在vue版本更迭中,尽管插槽的使用语法有部分变化,插槽的核心用法并未改变,鉴于vue2将在2023年第不再维护,以下我们将围绕vue3对插槽的具体使用方法进行展开。
当子组件中使用slot声明一个插槽出口API后,父组件在使用子组件时,可以选择将父组件内容渲染到子组件插槽部分,也可以选择不做渲染。
若父组件没有提供插槽内容,则不会渲染,子组件会使用其本身的默认内容进行页面渲染。我们来看如下示例:
子组件:SlotsComponent.vue
<template>
<div class="red-text">
<slot>
子组件插槽
slot>
div>
template>
<style scoped>
.red-text {
color: red;
}
style>
父组件:index.vue
<template>
<div>
<label>父组件label>
<SlotComponent>SlotComponent>
div>
template>
<script>
import SlotComponent from "./component/SlotsComponent";
export default {
components: {
SlotComponent
}
};
script>
渲染结果如下:
我们可以看到这个时候页面渲染的是子组件默认的内容。
再看父组件提供插槽内容的情况,子组件代码不变,父组件代码如下:
<template>
<div>
<label>父组件label>
<SlotComponent>
父组件使用子组件插槽
SlotComponent>
div>
template>
<script>
import SlotComponent from "./component/SlotsComponent";
export default {
components: {
SlotComponent
}
};
script>
渲染结果如下:
我们可以看到子组件插槽部分被父组件使用的插槽内容替换。以上是插槽的基本使用。
具名插槽,顾名思义,就是具有名称的插槽,在项目日常开发规范中,一搬公司都会要求使用具名插槽,以变后续组件的扩展和增强代码的可读性。
其次,若我们需要在子组件中声明多个插槽出口,也必须使用具名插槽,用于区分父组件的使用,具名插槽就是利用slot的name
属性给插槽命名,父组件中使用v-slot:slotName
来使用对应的插槽。
以下我们来看一下具名插槽的使用:
子组件:SlotsComponent.vue
<template>
<div class="red-text">
<header>
<slot name="header">
slot>
header>
<main>
<slot name="main">
slot>
main>
<footer>
<slot name="footer">
slot>
footer>
div>
template>
<script>
export default {};
script>
<style scoped>
.red-text {
color: red;
}
style>
父组件:index.vue
<template>
<div>
<label>父组件label>
<SlotComponent>
<template v-slot:header>
我是头
template>
<template v-slot:footer>
我是底
template>
SlotComponent>
div>
template>
<script>
import SlotComponent from "./component/SlotsComponent";
export default {
components: {
SlotComponent
}
};
script>
渲染结果如下:
我们可以看到渲染结果如上。通过该渲染结果,我们也知道若子组件声明了具名插槽,但是父组件使用。则不会在页面渲染(除非有默认值)。出自之外还有以下几个注意点:
,和部分vue低版本用法不同。在具名插槽的基础上,动态控制插槽的名称,成为动态插槽名,使用动态插槽,我们可以将父组件的内容动态渲染到到子组件插槽接口中。
使用方法如下:
父组件:
<template>
<div>
<label>父组件label>
<SlotComponent>
<template v-slot:[dynamicSlotName]>
我是动态插槽
template>
<template v-slot:footer>
我是底
template>
SlotComponent>
div>
template>
<script>
import SlotComponent from "./component/SlotsComponent";
export default {
components: {
SlotComponent
},
data() {
return {
dynamicSlotName: "header"
};
}
};
script>
渲染结果如下:
通常情况下,父子间插槽内容只能直接访问父组件的属性,当我们父组件需要使用子组件插槽属性时,我们可以用到插槽传值。
示例如下:
子组件:SlotsComponent.vue
<template>
<div class="red-text">
<header>
<slot :title="headerTitle" name="header">
slot>
header>
<main>
<slot name="main">
slot>
main>
<footer>
<slot name="footer">
slot>
footer>
div>
template>
<script>
export default {
data() {
return {
headerTitle: "我是子组件slot变量"
};
}
};
script>
<style scoped>
.red-text {
color: red;
}
style>
父组件:index.vue
<template>
<div>
<label>父组件label>
<SlotComponent>
<template v-slot:header="slotProps">
{{ slotProps.title }}
template>
<template v-slot:footer>
我是底
template>
SlotComponent>
div>
template>
<script>
import SlotComponent from "./component/SlotsComponent";
export default {
components: {
SlotComponent
},
data() {
return {
dynamicSlotName: "header"
};
}
};
script>
渲染结果如下:
其中,以上代码使用插槽传值,v-slot:header="slotProps"
,slotProps
可以读取到名字为header
插槽上所有的属性,比如我们在子组件slot中声明的title
属性。同样利用这个方法,可以传递多个属性到父组件的插槽内容中。
以上内容为了让读者更好理解插槽,降低学习成本,从事至终我们都是用同一个示例进行演示,以上代码为插槽的基本知识,从2.1到2.4为循序渐进过程。
天下难事,必作于易,天下大事,必作于细。从以上插槽的使用方法中,希望大家能理解并掌握插槽基本知识,这样以来,就可以进行融会贯通,应用于复杂的代码环境当中。同时若有写的不对的地方或者有什么建议,欢迎大家一起学习探讨。