Vue前端开发-动态插槽
不仅父组件可以通过插槽方式访问并控制子组件传入的数据,而且可以控制传入父组件时插槽的名称,从而使不同的插槽根据名称的不同,使用场景也不同,例如在一个小区详细页中,可以根据小区类型,调用不同名称的详细页插槽,这种插槽就是动态插槽。
接下来,结合一个完整的实例,来演示使用动态插槽,实现一个tab选项卡的功能。
实例7-6 动态插槽应用
1. 功能描述
在一个父组件中,添加一个子组件,子组件中是各种不同名称的slot插槽,当点击父组件选项卡标题时,就选中了一个插槽的名称,则在内容中,显示对应名称的插槽。
2. 实现代码
在项目的components 文件夹中,添加一个名为“Parent”的.vue文件,该文件的保存路径是“components/ch7/part6/”,在文件中加入如清单7-13所示代码。
代码清单7-13 Parent.vue代码
<template>
<ul>
<li :key="index" v-for="item,index in tabs"
:class="{ 'focus': index == sIdx }"
@click="clk(item.sName, index)">
{{ item.title }}
</li>
</ul>
<child>
<template #[sName]>
<div class="content">
{{ tabs[sIdx].content }}
</div>
</template>
</child>
</template>
<script>
import Child from "./Child.vue"
export default {
data() {
return {
tabs: [{
sName: "s1",
title: "新闻",
content: "新闻内容很丰富"
}, {
sName: "s2",
title: "热点",
content: "热点事件也不少"
}, {
sName: "s3",
title: "图片",
content: "图片资讯更精彩"
}],
sName: "s1",
sIdx: 0
}
},
methods: {
clk(n, i) {
this.sName = n;
this.sIdx = i
}
},
components: {
Child
}
}
</script>
<style scoped>
ul {
padding: 0;
margin: 0;
list-style: none;
display: flex;
justify-content: space-around;
width: 300px;
border: solid 1px #ccc;
}
ul>li {
padding: 8px;
cursor: pointer;
width: 84px;
text-align: center;
}
ul .focus {
background-color: #ccc;
font-weight: 700;
}
.content {
width: 260px;
border: solid 1px #ccc;
border-top: none;
padding: 20px;
}
</style>
在父组件中,导入子组件 Child.vue文件,它的功能是为父组件提供各类名称的模板,父组件根据slot插槽的name属性值就可以动态加载,它的代码如清单7-14所示。
代码清单7-14 Child.vue代码
<template>
<div v-for="(item, index) in names" :key="index">
<slot :name="item"></slot>
</div>
</template>
<script>
export default {
data() {
return {
names: ["s1","s2","s3"]
}
}
}
</script>
3. 页面效果
保存代码后,页面在Chrome浏览器下执行的页面效果如图7-7所示。
4. 源码分析
在本实例的子组件Child源码中,向父组件提供了多个不同name的slot插槽,供父组件中template元素使用,使用的方法是在模板中添加#符号,符号后面是slot插槽的名称,由于该名称是一个动态的变量sName,因此需要使用[]方括号进行包裹。
在父组件中,当用户点击某个导航栏选项时,在单击事件中获取到对应的slot插槽名称和索引号,则将前者传给变量sName,使父组件中template元素替换sName名称的插槽;后者传给变量sIdx,通过sIdx值获取到对应的数组内容,并显示在插槽中。