插槽(slot)是一种用于组件模版复用的技术,它允许你在子组件中预留一些位置,然后在父组件中填充内容。这样就可以在不同的地方使用同一个组件,但是在不同的地方显示不同的内容。
插槽主要分为默认插槽、具名插槽、动态插槽、插槽后备、作用域插槽。
默认插槽
// 父组件<div><slotChild>默认传值的方式</slotChild></div>
// 子组件
<template><div><slot></slot></div>
</template>
具名插槽
父组件的第一种写法
<slotChild><template v-slot:header><div>Title</div></template><div>具名插槽的内容</div>
</slotChild>
父组件内部内容的另一种写法
<template #header><div>Title</div>
</template>
<div>具名插槽的内容</div>
子组件的文件
<div><header><slot name="header">Default Header</slot></header><div><slot>default Content</slot></div>
</div>
动态插槽
parent.vue文件
<slotChild:headerSlotName="headerSlot":mainSlotName="mainSlot"><template v-slot:[headerSlot]><div>这是一个动态的头部</div></template><template v-slot:[mainSlot]><div>这是一个动态的内容渲染区域</div></template>
</slotChild>
import { defineComponent, onMounted, ref } from 'vue'
import slotChild from '@/components/slotChild.vue'export default defineComponent({name: 'parent',components: {slotChild},setup() {return {headerSlot: 'header',mainSlot: 'content',}}
})
slotChild.vue的文件
<div><header><slot :name="headerSlotName"></slot></header><main><slot :name="mainSlotName"></slot></main>
</div>
import { defineComponent } from "vue";export default defineComponent({name: 'slotChild',props: {headerSlotName: String,mainSlotName: String},
})
插槽后备
parent.vue文件
<slotChild><template v-slot:header><div>自定义头部内容</div></template>
</slotChild>
slotChild.vue文件
<div><header><slot name="header">Default Header</slot></header><main><slot name="main">默认的主体内容</slot></main>
</div>
在父组件中,只给header传值,主体内容采用默认的值。在大多数情况下,插槽后备与作用域插槽一起使用。
作用域插槽
parent.vue文件
<slotChild><template v-slot:default="slotProps"><div>{{slotProps.user.name}}</div></template><template v-slot:header="headerProps"><div>{{headerProps.header.title}}</div></template>
</slotChild>
slotChild.vue文件
<div><slot :user="user"></slot><slot name="header" :header="header"></slot>
</div>
import { defineComponent, reactive } from "vue";export default defineComponent({name: 'slotChild',setup() {const user = reactive({name:'summer',age: '18'})const header = reactive({title: '标题',avatar: 'img地址'})return {user,header}}
})