【前端9】手风琴:使用插槽实现动态内容插入的Vue组件
- 写在最前面
- 一、插槽的基本概念
- 1.默认插槽
- 2.具名插槽
- 二、实现一个折叠面板组件
- 0.关键点和注意事项
- 1.父组件 `App.vue`
- 2.子组件 `Collapse.vue`
- 总结
- 3.详细解读(可以略过)
- 父组件
- 子组件
- 三、小结
写在最前面
在开发Vue.js应用时,插槽(slot)是一个非常强大的工具,它允许我们在组件中插入动态内容。插槽提供了一种灵活的方式来组合组件,使组件变得更加可复用和模块化。
在这篇博客中,我们将介绍插槽的基本概念,并展示如何通过插槽实现一个折叠面板组件。
一、插槽的基本概念
插槽是Vue.js提供的一种机制,用于在组件内部定义占位符,并在使用组件时插入自定义内容。插槽主要有两种类型:
- 默认插槽:这是最简单的插槽形式,用于插入默认内容。
- 具名插槽:允许在组件中定义多个插槽,每个插槽都有一个独特的名字。
1.默认插槽
默认插槽是在组件模板中不指定名称的插槽。在使用组件时,可以将内容直接插入到默认插槽中。
<!-- ParentComponent.vue -->
<template>
<ChildComponent>
<p>This is some default content</p>
</ChildComponent>
</template>
<!-- ChildComponent.vue -->
<template>
<div>
<slot></slot>
</div>
</template>
2.具名插槽
具名插槽允许在组件中定义多个插槽,并在使用组件时通过插槽名称来插入内容。
<!-- ParentComponent.vue -->
<template>
<ChildComponent>
<template v-slot:header>
<h1>Header Content</h1>
</template>
<template v-slot:footer>
<p>Footer Content</p>
</template>
</ChildComponent>
</template>
<!-- ChildComponent.vue -->
<template>
<div>
<header>
<slot name="header"></slot>
</header>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
二、实现一个折叠面板组件
接下来,我们将通过插槽实现一个折叠面板组件,这个组件允许用户动态插入标题和内容。我们会将代码拆分为父组件和子组件,以便更好地展示插槽的使用。
0.关键点和注意事项
- 使用插槽传递动态内容:在父组件中通过
v-slot
指令插入动态内容,这使得子组件可以在不修改其内部结构的情况下展示不同的内容。 - 具名插槽:在子组件中使用具名插槽(如
header
和content
),以便在不同的位置插入不同的内容。 - 作用域插槽:在使用插槽时,通过
v-slot
指令传递参数,使得插槽内部的内容可以访问和使用子组件中的数据和方法。
1.父组件 App.vue
父组件将包含折叠面板组件,并使用插槽插入自定义内容。
<!-- 父组件把items的data传值给子组件 -->
<eiCollapse :items="items">
<!-- 子组件传值,父组件解构出来 -->
<template v-slot:header="{ item }">
- 在
eiCollapse
组件中,传递一个items
属性。 - 使用具名插槽
header
来定义每个item
的标题显示方式。 - 在插槽模板中,通过
item.title
来显示每个item
的标题。
这样可以使 eiCollapse
组件更加灵活,允许父组件自定义每个 item
的标题显示内容。
<template>
<div id="app">
<eiCollapse :items="items">
<template v-slot:header="{ item }">
{{ item.title }}
</template>
<template v-slot:content="{ item }">
<div v-for="content in item.contents" :key="content">{{ content }}</div>
</template>
</eiCollapse>
</div>
</template>
<script>
import eiCollapse from './components/eiCollapse.vue';
export default {
components: {
eiCollapse
},
data() {
return {
items: [
{
title: "一致性 Consistency",
name: "1",
contents: [
"与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;",
"在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。"
]
},
{
title: "反馈 Feedback",
name: "2",
contents: [
"控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;",
"页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。"
]
},
{
title: "效率 Efficiency",
name: "3",
contents: [
"简化流程:设计简洁直观的操作流程;",
"清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;",
"帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。"
]
},
{
title: "可控 Controllability",
name: "4",
contents: [
"用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;",
"结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。"
]
}
]
};
}
};
</script>
2.子组件 Collapse.vue
子组件定义了折叠面板的结构,并使用插槽来插入标题和内容。
每个折叠项包括一个标题和内容部分。通过具名插槽 header
和 content
,父组件可以自定义每个折叠项的标题和内容。点击标题时,会调用 toggle
方法切换折叠项的显示状态。
其中,JavaScript 表达式:
this.activeName = this.activeName === name ? '' : name;
用于在 Vue 组件中切换 [activeName
]的值。具体来说,它实现了折叠面板的展开和收起功能。
-
this.activeName
:this
指向当前 Vue 组件实例。activeName
是组件实例中的一个数据属性,用于存储当前激活(展开)的折叠项的名称。
-
三元运算符
? :
:- 这是一个条件(三元)运算符,语法为
condition ? expr1 : expr2
。 - 如果
condition
为真,返回expr1
;否则返回expr2
。
- 这是一个条件(三元)运算符,语法为
-
条件判断
this.activeName === name
:- 判断当前激活的折叠项名称是否等于传入的
name
。 - 如果相等,表示当前折叠项已经是展开状态。
- 判断当前激活的折叠项名称是否等于传入的
-
结果赋值:
- 如果
this.activeName === name
为真,表示当前折叠项已经展开,此时将activeName
设为空字符串''
,即收起折叠项。 - 如果
this.activeName !== name
为假,表示当前折叠项未展开,此时将activeName
设为name
,即展开折叠项。
- 如果
总结
这行代码的作用是切换折叠项的展开和收起状态。如果当前折叠项已经展开,则收起它;如果当前折叠项未展开,则展开它。通过这种方式,可以实现折叠面板的交互效果。
<template>
<div>
<div class="collapse" v-for="item in items" :key="item.name">
<div class="collapse-header" @click="toggle(item.name)">
<slot name="header" :item="item" :toggle="toggle"></slot>
</div>
<div v-show="activeName === item.name" class="collapse-content">
<slot name="content" :item="item"></slot>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
items: {
type: Array,
required: true
}
},
data() {
return {
activeName: ''
};
},
methods: {
toggle(name) {
console.log(name);
this.activeName = this.activeName === name ? '' : name;
}
}
};
</script>
<style>
.collapse {
border: 1px solid #dcdfe6;
margin-bottom: 10px;
border-radius: 4px;
}
.collapse-header {
background-color: #f5f7fa;
padding: 10px 16px;
font-weight: 500;
cursor: pointer;
}
.collapse-content {
padding: 10px 16px;
border-top: 1px solid #dcdfe6;
}
</style>
3.详细解读(可以略过)
父组件
-
eiCollapse
组件:- 这是一个自定义组件,名称为
eiCollapse
。 - 通过
:items="items"
绑定了一个名为items
的属性,items
是父组件中的一个数据属性。
- 这是一个自定义组件,名称为
-
具名插槽
header
:- 使用了 Vue 的
v-slot
指令来定义一个具名插槽header
。 - 插槽的内容是一个
<template>
元素,表示插槽的内容模板。
- 使用了 Vue 的
-
插槽作用域:
{ item }
是插槽的作用域对象,表示eiCollapse
组件会传递一个item
对象到插槽中。- 在插槽模板中,可以使用
item
对象的属性。
-
插槽内容:
{{ item.title }}
是插槽内容,使用了 Vue 的插值语法来显示item
对象的title
属性。
子组件
-
v-for
指令:v-for="item in items"
表示循环遍历items
数组,为每个item
渲染一个div
元素。:key="item.name"
为每个div
元素设置唯一的key
,以便 Vue 能够高效地更新渲染。
-
折叠标题部分:
<div class="collapse-header" @click="toggle(item.name)">
定义了折叠项的标题部分。@click="toggle(item.name)"
表示点击标题时调用toggle
方法,并传递item.name
作为参数。
-
具名插槽
header
:<slot name="header" :item="item" :toggle="toggle"></slot>
定义了一个具名插槽header
。- 插槽传递了两个属性:
item
和toggle
,父组件可以通过这些属性自定义插槽内容。
-
折叠内容部分:
<div v-show="activeName === item.name" class="collapse-content">
定义了折叠项的内容部分。v-show="activeName === item.name"
控制内容的显示和隐藏,只有当activeName
等于item.name
时,内容才会显示。
-
具名插槽
content
:<slot name="content" :item="item"></slot>
定义了一个具名插槽content
。- 插槽传递了
item
属性,父组件可以通过这个属性自定义插槽内容。
三、小结
通过插槽,我们可以实现灵活和可复用的Vue组件。插槽不仅允许我们在组件中插入动态内容,还使得组件间的通信变得更加简洁和高效。
希望通过这篇博客,您对插槽有了更深入的理解,并能够在实际项目中灵活运用。
hello,我是 是Yu欸 。如果你喜欢我的文章,欢迎三连给我鼓励和支持:👍点赞 📁 关注 💬评论,我会给大家带来更多有用有趣的文章。
原文链接 👉 ,⚡️更新更及时。
欢迎大家添加好友交流。