官方文档链接:cn.vuejs.org/guide/compo…
1.0 插槽内容与出口
含义:通过使用插槽,
子组件仅负责渲染外层的,而其内部的内容由父组件提供。我的理解:子组件提供的
插槽出口,父组件填写的对应内容为插槽内容
示图:
1.1 默认内容
//子组件中
<slot>
Submit <!-- 默认内容 -->
</slot>
//父组件写入内容时,会替换`整个插槽slot`
1.2 具名插槽
- slot 添加 name="nameID" 属性
为什么要用?
子组件有多个插槽, 就需要用到
父组件怎么指定插槽出口呢? 用v-slot:nameID 和 #nameID
// 子组件BaseLayout
<div class="container">
<slot></slot>
<slot name="header"><!-- 具名 --></slot>
<slot name="footer"><!-- 具名 --></slot>
</div>
// 父组件
<BaseLayout>
<template v-slot:header> <!-- header 插槽的内容放这里 --> </template>
<template #footer> <!-- footer 插槽的内容放这里 --> </template>
</BaseLayout>
1.3 默认插槽
其中1.1 就是默认插槽
- 父组件怎么用呢? 1.1也告诉我们了, 直接填写,
隐式的默认插槽 - 或者使用
<template #default>
1.4 条件插槽
结合使用 $slots 属性与 v-if 来实现
// 子组件中
<div v-if="$slots.header" class="card-header">
<slot name="header" />
</div>
1.5 动态插槽名
- [dynamicSlotName]
// 父组件中
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
<!-- 缩写为 -->
<template #[dynamicSlotName]>
...
</template>
</base-layout>
子组件格式: <slot name='插槽名称name' :属性名1="方法/对象" :属性名2="方法/对象">
注:属性可以传多个
<!-- 子组件:ChildComponent.vue -->
<template>
<div>
<slot :myMethod="childMethod"></slot>
</div>
</template>
<script>
export default {
methods: {
childMethod() {
console.log('Child method executed');
}
}
}
</script>
2.0 作用域插槽
是什么?
普通情况,插槽出口内容无法访问到子组件的状态, 子组件在渲染时将数据提供给插槽出口
2.1 默认插槽和具名插槽的区别
2.1.1 默认插槽
// 默认插槽
<!-- 子组件 <MyComponent> 的模板 -->
<div>
<slot :text="greetingMessage" :count="1"></slot>
</div>
//父组件中
<MyComponent v-slot="slotProps">
{{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
需要解释下:
解释:
// 解释上图
function MyComponent(slots) {
const greetingMessage = 'hello'
return `<div>${
// 在插槽函数调用时传入 props
slots.default({ text: greetingMessage, count: 1 })
}</div>`
}
MyComponent({
// 类比默认插槽,将其想成一个函数
default: (slotProps) => {
return `${slotProps.text} ${slotProps.count}`
}
})
v-slot="slotProps" 可以类比这里的函数签名,和函数的参数类似,我们也可以在 v-slot 中使用解构:
// 父组件中
<MyComponent v-slot="{ text, count }">
{{ text }} {{ count }}
</MyComponent>
2.1.2 具名插槽
v-slot:name="slotProps"
#name="slotProps"
向具名插槽中传入 props:
<slot name="header" message="hello"></slot>
- 注意 默认插槽和具名插槽都支持 静态绑定和动态绑定
message="hello" // 静态绑定
:text="greetingMessage" // 动态绑定
3. 示例:
没有设置插槽名 默认#default
父组件中: <template #插槽名="{ 属性1, 属性2, ... }"></template>
属性可以接受多个,属性也可以是方法,函数对象,
只取一个可以不用{}接受
当属性1是函数对象时,父组件可以这样使用 @click='属性1'
<!-- 父组件 -->
<template>
<div>
<child-component>
<!-- 使用作用域插槽传递函数对象 -->
<template #default="{ myMethod }">
<button @click="myMethod">Click me</button>
</template>
</child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
methods: {
parentMethod() {
console.log('Parent method executed');
}
}
}
</script>
总结
插槽slot:父组件向子组件传递元素:父组件发送,子组件接受
插槽作用域:子组件向插槽出口传递数据或方法,如果是方法,父组件又可以通过方法对象操作子组件