vue3中实现展开折叠功能,当数据较少时隐藏展开折叠按钮,且支持单选和多选
效果
折叠效果
展开效果
数据较少时隐藏展开折叠按钮
单选效果
多选效果
代码
<template>
<div class="slider-container">
<div class="allShowList-container">
<div :class="['allShowList', iSCollapse ? 'noWrap' : 'wrap']" :ref="`allShowList-${type}`">
<div v-for="(item, index) in scrollList" :key="index" class="slide">
<div :title="item[showKey]" :class="['slider-item', computedSelectClass(item)]" @click="handlerClick(item)">
{{ item[showKey] }}
</div>
</div>
</div>
<div class="collapse-btn" @click="handlerCollapse" v-if="flag">
{{ iSCollapse ? '展开' : '折叠' }}
<el-icon v-if="iSCollapse"><CaretBottom /></el-icon>
<el-icon v-else><CaretTop /></el-icon>
</div>
</div>
</div>
</template>
<script setup name="carouselScroll">
import { ref, getCurrentInstance, nextTick, watch } from 'vue'
const { proxy } = getCurrentInstance()
const props = defineProps({
scrollList: {
required: true,
type: Array,
default: () => []
},
showKey: {
type: String,
default: ''
},
valueKey: {
type: String,
default: ''
},
type: {
type: String,
default: ''
},
multiple: {
type: Boolean,
default: false
}
})
const selectedList = ref([])
const emit = defineEmits(['handlerItemClick'])
// 计算选中样式
const computedSelectClass = item => {
const index = selectedList.value.findIndex(k => k === item[props.valueKey])
if (index > -1) {
return 'selected'
} else {
return ''
}
}
// 点击选中
const handlerClick = item => {
const index = selectedList.value.findIndex(k => k === item[props.valueKey])
if (index > -1) {
props.multiple ? selectedList.value.splice(index, 1) : (selectedList.value = [])
} else {
props.multiple ? selectedList.value.push(item[props.valueKey]) : (selectedList.value = [item[props.valueKey]])
}
computedSelectClass(item)
let data = null
if (props.multiple) {
data = selectedList.value.join()
} else if (selectedList.value.length > 0) {
data = selectedList.value[0]
}
emit('handlerItemClick', {
data: data,
type: props.type
})
}
// 展开折叠
const iSCollapse = ref(true)
const handlerCollapse = () => {
iSCollapse.value = !iSCollapse.value
}
// 是否显示折叠按钮
const flag = ref(false)
const isShowCollapseBtn = () => {
const domRef = `allShowList-${props.type}`
if (proxy.$refs[domRef]) {
flag.value = proxy.$refs[domRef].scrollHeight > 36
}
}
watch(
() => [props.type, props.scrollList],
([newType, newScrollList]) => {
if (newType && newScrollList) {
nextTick(() => {
isShowCollapseBtn()
})
}
},
{
immediate: true
}
)
</script>
<style lang="scss" scoped>
.slider-container {
position: relative;
width: 100%;
overflow: hidden;
.allShowList-container {
display: flex;
.allShowList {
width: calc(100% - 50px);
min-height: 24px;
display: flex;
flex-wrap: wrap;
overflow: hidden;
&.wrap {
height: auto;
}
&.noWrap {
height: 24px;
}
.slide {
max-width: 84px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
margin-right: 40px;
padding-bottom: 12px;
box-sizing: border-box;
.slider-item {
width: 100%;
font-size: 14px;
color: #333333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.selected {
font-size: 14px;
color: #2e75ff;
}
}
}
.collapse-btn {
cursor: pointer;
font-size: 14px;
color: rgba(51, 51, 51, 0.6);
}
}
}
</style>
单选调用
<carouselScroll
:key="queryParams.deptId"
:scrollList="systemIds_option"
type="systemIds"
showKey="systemName"
valueKey="id"
@handlerItemClick="handlerItemClick"
/>
多选调用
<carouselScroll
:key="queryParams.deptId"
:scrollList="equipmentTypeId_option"
:multiple="true"
type="equipmentTypeId"
showKey="typeName"
valueKey="id"
@handlerItemClick="handlerItemClick"
/>