效果如下:
1.在components目录下新建个文件SubjectCatalog.vue组件,代码如下:
<template>
<div class="subject-catalog">
<div class="select">
<span class="select-name" @click="allBook">所有绘本</span>
</div>
<div v-for="(item,index) in optList" :key="index" class="select">
<span class="select-name" @click="manageUser(index)">{{ selectData[item.value] === ''? item.name :selectData[item.value] }}
<i :class="[ 'el-icon-caret-bottom' , selectFlag === index? 'handstands' : 'handstand']" />
</span>
<ul :ref="item.value" :class="['select-box' ,selectFlag === index? '' : 'select-box-hide']">
<li v-for="(item1,index1) in item.children" :key="index1" class="select-li" @click="optionClick(item1.value,item.value)">
{{ item1.name }}
</li>
</ul>
</div>
</div>
</template>
/*
分类选择组件
optList: 分类列表
choseOpt: 分类列表下选中的值
*/
<script>
export default {
name: 'SubjectCatalog',
props: {
optList: {
type: Array,
default() {
return []
} },
choseOpt: {
type: Object,
default() {
return {}
} }
},
data() {
return {
selectFlag: -1, // 当前选中的下拉框
selectData: this.choseOpt // 选中的值
}
},
methods: {
// 展开的下拉框
manageUser(index) {
if (this.selectFlag === index) {
this.selectFlag = -1
} else {
this.selectFlag = index
}
},
// 选中的值
optionClick(value, name) {
this.selectData[name] = value
this.selectFlag = -1
// 把选中的值传递给父组件
this.$emit('select-data', this.selectData)
},
// 点击所有绘本
allBook() {
// 遍历对象,初始化值
Object.keys(this.selectData).forEach((key) => {
this.selectData[key] = ''
})
}
}
}
</script>
<style lang="less">
.subject-catalog {
.vw(180);
height: auto;
color: #fff;
.select {
margin-bottom: 8px;
.select-name {
display: inline-block;
.vw(150);
.vh(50);
.line-height(50);
cursor: pointer;
text-align: center;
background-color: @BASE_DM;
}
.select-box {
max-height: 15vh;
overflow: hidden;
transition: max-height 0.6s;
.select-li {
&:hover {
background-color: #98A8A7 !important;
}
display: inline-block;
.vw(150);
.vh(50);
.line-height(50);
cursor: pointer;
text-align: center;
background-color: #547374;
}
}
.select-box-hide {
max-height: 0;
}
.handstands {
transition: all .3s;
}
.handstand {
transform:rotate(180deg);
transition: all .3s;
}
}
}
</style>
2.在父组件中应用封装好的组件
<template>
<div class="picture-list-container">
<SubjectCatalog :opt-list="optList" :chose-opt="choseOpt" @select-data="selectValue" />
</div>
</template>
<script>
// 引入组件
import SubjectCatalog from '../../components/SubjectCatalog.vue'
export default {
name: 'PictureList',
components: {
SubjectCatalog
},
data() {
return {
optList: [
{ name: '年龄',
value: 'age',
children: [
{
name: '3~6岁',
value: '3-6'
},
{
name: '6~8岁',
value: '6-8'
}
]
},
{ name: '主题',
value: 'theme',
children: [
{
name: '音乐',
value: '音乐'
},
{
name: '艺术',
value: '艺术'
}
]
},
{ name: '难度',
value: 'difficulty',
children: [
{
name: '一般',
value: '一般'
},
{
name: '较难',
value: '较难'
}
]
}
],
choseOpt: {
age: '', // 年龄
theme: '', // 主题
difficulty: '' // 难度
}
}
},
methods: {
// 选中的值
selectValue(id) {
console.log('我是选中的值', id)
}
}
}
</script>
注意事项:
在组件中有个selectData: this.choseOpt的赋值,看起来显得多余,但这是必须的,因为props的值是父组件传过来的,我们不能直接在子组件直接修改父组件传过来的值.这不仅会报警告,也破坏了单向数据流的设想.所以我们可以在子组件再声明一个变量,然后把父组件传过来的值赋给这个变量,我们再修改,就可以了.