我们都知道vue的插槽及使用,一下是探究他的背后,不对的地方欢迎指正
父组件中我们在子组件中嵌套插槽,在子组件中我们使用template模板写下对应的插槽
实际上父组件中经过编译传递给子组件的插槽是函数
此图为下面示例中子组件中的输出
default是默认插槽
footer是传的动态插槽
head是传的作用域插槽
title是传的具名插槽
然后 我们在子组件中 通过调用 slots.xxx 即插槽的名字 返回的是对应的虚拟dom,(数据结构之所以是数组对象 因为插槽中的节点可能是多个 )
此时 我们调用 vue的 创建dom方法 createElementVNode
最终的效果是和 template 写出来的一样的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>深入理解vue插槽</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app"></div>
<script>
const { createApp, createElementVNode } = Vue
const app = createApp({
template: `
<parent-component></parent-component>
`
})
app.component('parent-component', {
setup () {
const dynamicSlot = Vue.ref('footer')
return { dynamicSlot }
},
template: `
<div>
<child-component :slotName="dynamicSlot">
<template #default>
<p>默认插槽</p>
</template>
<template #head="{ message }">
<h1>作用域插槽----{{ message }}</h1>
</template>
<template #title>
<p>具名插槽</p>
</template>
<template #[dynamicSlot]>
<p>动态插槽</p>
</template>
</child-component>
</div>
`
})
app.component('child-component', {
props:{
slotName:{
type:String
}
},
setup (props, { slots }) {
console.log(slots, 'slots--',props)
const _default = slots.default()
const head = slots.head({ message: '你好' })
const title = slots.title()
const propslotName = slots[props.slotName]()
console.log(_default,head,title,propslotName)
return () => {
return createElementVNode('div', null, [
..._default, ...head, ...title, ...propslotName
])
}
},
/* template: `
<div>
<slot></slot>
<slot name="head" :message="'你好'"></slot>
<slot name="title"></slot>
<slot :name="slotName"></slot>
</div>
` */
})
app.mount('#app')
</script>
</body>
</html>