插槽的本质
复习插槽的概念:
- 子组件:通过 slot 来设置插槽
- 父组件:使用子组件时可以往 slot 的位置插入模板内容
插槽使用层面的本质:父组件向子组件传递模板内容
- 默认插槽:拥有默认的一些内容
- 具名插槽:给你的插槽取一个名字
- 作用域插槽:数据来自于子组件,通过插槽的形式传递给父组件使用
父组件传递内容的本质
传递的是一个对象:
js
{
default: function(){ ... },
xxx: function(){ ... },
xxx: function(){ ... },
}
对于上面的例子来讲,父组件传递的就是这样的一个对象:
jsx
{
default: function(){
// 注意返回值是对应结构的虚拟 DOM
return (
<div class="card-content">
<img src="./assets/landscape.jpeg" alt="Beautiful landscape" class="card-image" />
<p>探索未知的自然风光,记录下每一个令人惊叹的瞬间。加入我们的旅程,一起见证世界的壮丽。</p>
</div>
)
},
header: function(){
return (
<div>摄影作品</div>
)
}
}
父组件向子组件传递过去的东西本质上是函数,通过调用这些函数,能够得到对应结构的虚拟 DOM.
子组件设置插槽的本质
其实就是对父组件传递过来的函数进行调用,得到对应的虚拟 DOM.
js
const slots = {
default: function(){ ... },
xxx: function(){ ... },
xxx: function(){ ... },
}; // 该对象是父组件传递过来的对象
slots.default(); // 得到要渲染的虚拟DOM
slots.header(); // 得到要渲染的虚拟DOM
slots.xxx(); // 得到要渲染的虚拟DOM
进行验证
最后,我们需要对上面的说法进行验证。
js
import { defineComponent, h, ref } from 'vue'
import styles from './CardComponent.module.css'
export default defineComponent({
name: 'CardComponent',
setup(_, { slots }) {
const title = ref('这是子组件标题222')
const deaultSlotsVNode = slots.default()
let headerSlotsVnode = null
// 如果传递了header插槽,就调用header插槽
if (slots.header) {
headerSlotsVnode = slots.header({
title: title.value
})
}
// 但是要注意,调用了之后,不见得有值,所以要判断一下
if (!headerSlotsVnode.length) {
headerSlotsVnode = h('div', null, '默认标题')
}
return () =>
h('div', { class: styles.card }, [
h('div', { class: styles['card-header'] }, headerSlotsVnode),
h('div', { class: styles['card-body'] }, deaultSlotsVNode)
])
}
})
-EOF-