1. Simple
Father.vue
<template>
<FancyButton> Click me! </FancyButton>
</template>
FancyButton.vue
<template>
<button>
<slot></slot>
</button>
</template>
渲染的时候,<slot></slot>
会被替换为Click me!
2. 默认内容
父组件没传值使用自己的,如果传值了则替换
<template>
<button>
<slot>
Submit <!-- 默认内容 -->
</slot>
</button>
</template>
3. 具名插槽
Father.vue
<template>
<Son>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
//外层的template可写可不写,不写就是默认default
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here some contact info</p>
</template>
</Son>
</template>
<template>
<Son>
<template #header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template #footer>
<p>Here some contact info</p>
</template>
</Son>
</template>
Son.vue
<template>
<div>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
4. 条件插槽
<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>
5. 动态插槽
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
<!-- 缩写为 -->
<template #[dynamicSlotName]>
...
</template>
</base-layout>
6. 作用域
- 通常情况下,插槽由父组件传值,也只能获取父组件的响应式数据
6.1 使用子组件作用域
Father.vue
<template>
<div>
<Son v-slot:default="slotProps">
{{slotProps.usertext.firstName}}
</Son>
</div>
</template>
缩写1:default
<div>
<!-- 可以把 :default 去掉,仅限于默认插槽 -->
<Son v-slot="slotProps">
{{slotProps.usertext.firstName}}
</Son>
</div>
缩写二:#字號
<Son>
<template #header="headerProps">
{{ headerProps }}
</template>
<template #default="defaultProps">
{{ defaultProps }}
</template>
<template #footer="footerProps">
{{ footerProps }}
</template>
</Son>
Son.vue
<template>
<div>
<!-- 设置默认值:{{user.lastName}}获取 Jun -->
<!-- 如果home.vue中给这个插槽值的话,则不显示 Jun -->
<!-- 设置一个 usertext 然后把user绑到设置的 usertext 上 -->
<slot v-bind:usertext="user">{{user.lastName}}</slot>
<!-- 缩写 -->
<slot :usertext="user">{{user.lastName}}</slot>
</div>
</template>
<scripr setup lang='ts'>
import {ref,reactive} from 'vue'
const user = reactive({
firstName:"Fan",
lastName:"Jun"
})
</script>
6.2 多插槽
多插槽必须单独给每一个插槽赋值
<test>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
<template v-slot:other="otherSlotProps">
...
</template>
</test>
6.3 解构插槽Prop
常规写法:父组件
<div>
<test v-slot="slotProps">
{{slotProps.usertext.firstName}}
</test>
</div>
缩写:
<div>
<test v-slot={usertext}>
{{usertext.firstName}}
</test>
</div>
不知道行不行
<div>
<test #default={usertext}>
{{usertext.firstName}}
</test>
</div>
将usertext 重命名为 person
<div>
<test v-slot={usertext:person}>
{{person.firstName}}
</test>
</div>
定义默认内容,用于插槽没有值时的情形
<div>
<test v-slot="{usertext={firstName:'Yang'}}">
{{usertext.firstName}}
</test>
</div>