顶部筛选条件很多时,就需要对赛选条件进行分组,每组都要有展开收起,根据页面自定义,还需要显示收起查询中有几条查询中的内容
思路: 封装一个组件,利用插槽自定义查询条件和分组
// 子组件
<script setup>
import { onMounted, onUnmounted, ref } from 'vue'const props = defineProps({/*** data [{ slot: '', name: ''}]*/data: {type: Array,required: true,default: () => {return []}},labelStyle: {type: Object,default: () => {return {}}}
})const slotWrapperConfig = ref({})const buttonCommonConfig = {0: {text: '收起',iconClass: 'el-icon-arrow-up'},1: {text: '展开',iconClass: 'el-icon-arrow-down'},btnId: '_btn',btnChild: {spanId: '_child_span',iconId: '_child_icon'}
}const setSlotWrapper = () => {for (let i of props.data) {const slotWrapper = document.getElementById(i.slot)let btnStatus = 1const s = slotWrapperConfig.value[i.slot]if (s && s.hasOwnProperty('btnStatus')) {btnStatus = s.btnStatus}slotWrapperConfig.value[i.slot] = {el: slotWrapper,offsetWidth: slotWrapper.offsetWidth,children: slotWrapper.children,selected: 0,btnStatus}}
}const setMarkAndButton = () => {for (let k in slotWrapperConfig.value) {let child = slotWrapperConfig.value[k].childrenlet w = 0let l = []for (let i of child) {i.mr = parseFloat(window.getComputedStyle(i).marginRight)i.w = i.offsetWidth || i.ww += i.w + i.mrif (w > slotWrapperConfig.value[k].offsetWidth) {if (i.type !== 'button') {i.id = 'collapse'l.push(i)if (slotWrapperConfig.value[k].btnStatus === 1) {i.style.display = 'none'}}} else {if (i.outerHTML.includes('date')) {i.style.display = 'inline-flex'} else {i.style.display = 'block'}if (i.type !== 'button') {i.id = ''}}}slotWrapperConfig.value[k].collapse = lslotWrapperConfig.value[k].selected = getSelectedNum(slotWrapperConfig.value[k].collapse)const {btnId} = buttonCommonConfigif (slotWrapperConfig.value[k].collapse.length > 0) {slotWrapperConfig.value[k].button = createButton({btnId: `${k}${btnId}`,conf: slotWrapperConfig.value[k],btnClick: () => {for (let i of slotWrapperConfig.value[k].children) {if (slotWrapperConfig.value[k].btnStatus) {if (i.outerHTML.includes('date')) {i.style.display = 'inline-flex'} else {i.style.display = 'block'}} else {if (i.id === 'collapse') {i.style.display = 'none'}}}slotWrapperConfig.value[k].btnStatus = Number(!slotWrapperConfig.value[k].btnStatus)slotWrapperConfig.value[k].selected = getSelectedNum(slotWrapperConfig.value[k].collapse)changeButtonChild(`${k}${btnId}`, slotWrapperConfig.value[k])}})changeButtonChild(`${k}${btnId}`, slotWrapperConfig.value[k])const btnEl = document.getElementById(`${k}${btnId}`)if (!btnEl) {slotWrapperConfig.value[k].el.append(slotWrapperConfig.value[k].button)}} else {const btnEl = document.getElementById(`${k}${btnId}`)if (btnEl) {btnEl.remove()}}}
}const changeButtonChild = (btnId, conf) => {let t = ''if (conf.selected > 0 && conf.btnStatus === 1) {t = ` 已选(${conf.selected})个`}const {btnChild: {spanId, iconId}} = buttonCommonConfiglet btnSpan = document.getElementById(`${btnId}${spanId}`)if (btnSpan) {btnSpan.innerText = `${buttonCommonConfig[conf.btnStatus].text}${t}`}let btnIcon = document.getElementById(`${btnId}${iconId}`)if (btnIcon) {btnIcon.className = buttonCommonConfig[conf.btnStatus].iconClass}
}const createButton = (options) => {let {btnId} = optionsif (!btnId) {return}let btn = document.createElement('button')btn.id = btnIdbtn.type = 'button'btn.className = 'el-button el-button--default el-button--small'const {btnChild: {spanId, iconId}} = buttonCommonConfiglet btnSpan = document.createElement('span')btnSpan.id = `${btnId}${spanId}`let btnIcon = document.createElement('i')btnIcon.id = `${btnId}${iconId}`let t = ''if (options.conf.selected > 0) {t = ` 已选(${options.conf.selected})个`}btnSpan.innerText = `${buttonCommonConfig[options.conf.btnStatus].text}${t}`btnIcon.className = buttonCommonConfig[options.conf.btnStatus].iconClassfor (let i of [btnSpan, btnIcon]) {btn.append(i)}btn.onclick = () => options.btnClick()return btn
}const getSelectedNum = (list) => {const c = _.compact(_.map(list, i => {if (typeof i.__vue__.value === 'object') {if (!_.isEmpty(i.__vue__.value)) {return i.__vue__.value}} else {if (i.__vue__.value === 0) {return 1}return i.__vue__.value}}))return c.length
}const init = () => {setSlotWrapper()setMarkAndButton()
}onMounted(() => {init()window.addEventListener('resize', init)
})onUnmounted(() => {window.removeEventListener('resize', init)
})</script><template><div class="search_wrapper"><div v-for="item in data" class="list_item"><div><div class="name" :style="labelStyle">{{ item.name }}</div></div><div :id="item.slot" class="slot_item"><slot :name="item.slot"></slot></div></div></div>
</template><style lang="scss">
.search_wrapper {.list_item {display: flex;.name {width: 50px;height: 32px;line-height: 32px;margin: 10px 10px 0 0;color: #333333;font-size: 15px;font-weight: 600;text-align: right;}}.slot_item {width: 100%;display: flex;flex-wrap: wrap}
}
</style>
<template><div class="user-box"><div><v-SearchBar :data="slotData" :labelStyle="{width: 'max-content', fontWeight: '400', fontSize: '14px'}"><template #laiyuan>...添加筛选条件就可以了</template ></v-SearchBar></div></div>
</template>// 父
组件
data () {
return {
slotData: [{name:'来源',slot:'laiyuan',},{name:'状态',slot:'status',},{name:'产品',slot:'product'},{name:'用户',slot:'admin'},{name:'时间',slot:'time'},],
}
}
最终效果