本篇文章内容将会讲解到,插槽与具名插槽以及嵌套插槽的使用方法和场景
插槽 < slot />
插槽简单的来说就是将写在父组件里的内容插入到子组件里
需求:在子组件中显示 '这就是插槽' 几个字
使用方法
1.首先在父组件中引用Dialog子组件,并在中间写入内容
//这是父组件里的代码,引入子组件Dialog
<Dialog >
<h2>这就是插槽</h2>
</Dialog>
2.告诉子组件在那个地方插入,使用
//这是子组件Dialog的内容
<template>
<p>下面就是插槽插入的位置</p>
//slot就是插入的地方
<slot />
</template>
这样的插槽很简单,但是只能插入一个地方,我要是想在不同的地方插入不同的内容,这该怎么办呢?这就该使用具名插槽
具名插槽
具名插槽就是带有名字的插槽,一个名字一个坑
需求:将标题插入到header里,将内容插入到main里
使用方法
1.在父组件将不同的内容使用template包裹,并使用v-slot起一个名字
<Dialog >
<template v-slot:title>
<h2>具名插槽</h2>
</template>
<template v-slot:content>
<p>第一行</p>
<p>第八行</p>
</template>
</Dialog>
v-slot可以使用#代替,效果是一样的
<Dialog >
<template #title>
<h2>具名插槽</h2>
</template>
<template #content>
<p>第一行</p>
<p>第八行</p>
</template>
</Dialog>
2.在子组件将插槽使用名字匹配
<template>
<div class="gulu-dialog">
<header>
<slot name="title" />
</header>
<main>
<slot name="content" />
</main>
<footer>
<Button @click="ok" level="main">OK</Button>
<Button @click="cancel">Cancel</Button>
</footer>
</div>
</template>
嵌套插槽
在父组件里写一个子组件,并且子组件里嵌套着孙子组件,如何将孙子组件的内容也渲染到页面上?
需求:将 导航1 和 内容1 都显示到页面上
父组件的代码
<template>
<div>
<h1>Tabs组件</h1>
<Tabs>
<Tab title="导航1">内容1</Tab>
<Tab title="导航2">内容2</Tab>
</Tabs>
</div>
</template>
1.在孙子组件写上插槽
<template>
<div>
<slot />
</div>
</template>
2.使用context
在子组件获取父组件传递的内容,
context.slots.default()
可以获取到父组件传递的标签对象结构
- 可以使用
component
在子组件的模板上将内容渲染,但是只能将内容1,内容2显示到页面上。标签里的title内容显示不出来
<component v-for="(c,index) in defaults" :is="c" :key="index" />
- 使用forEach 或者map可以遍历到标签对象,这样就可以调用里面的属性了 此时titles里面存储的就是标签里的title数组了,
const titles = defaults.map((tag) => {
return tag.props.title
})
子组件完整的代码
<template>
<div>
<div v-for="(t,index) in titles" :key="index">{{t}}</div>
<component v-for="(c,index) in defaults" :is="c" :key="index" />
</div>
</template>
<script lang="ts">
import Tab from './Tab.vue'
export default {
setup(props, context) {
//获取标签对象数组
const defaults = context.slots.default()
//这个可以检查传递的组件是否是孙子组件
defaults.forEach((tag) => {
if (tag.type !== Tab) {
throw new Error('Tabs 子标签必须是Tab')
}
})
//获取标签里的title属性数组
const titles = defaults.map((tag) => {
return tag.props.title
})
return {
defaults,
titles
}
}
}
</script>
总结
标签对象属性组.type !== Tab
可以判断传递过来的孙子组件是不是Tab类型的context.slots.default()
可以获取传递的插槽内容component
组件可以渲染出传递的标签- 在使用 v-for遍历时要使用:key 但是使用index有时可能会出现bug,这个下回再深究