vue3封装筛选项
背景
项目开发中遇到筛选项,并且几个页面都有使用,依次写,太过于繁琐
筛选项解构如下
封装全局组件fjj-content
<template>
<div class="fjj-content">
<ul class="flex-col fjj-list">
<li v-for="(item, index) in list" :key="index">
<!-- custom 单选、多选 item.isMutiple 是否支持多选 -->
<div v-if="item.type === 'custom'">
<!-- item.isMutiple true 多选 -->
<div class="flex-row">
<span class="label-box">{{ item.title }}:</span>
<ul class="flex-row tags-list items-center">
<!-- 选中默认项 -->
<li
:class="{ activeLi: item.defaultSelect }"
class="justify-center items-center"
@click="selectDefault(item.detailList, item.isMutiple, item)"
>
<span> {{ item.defaultLabel }}</span>
</li>
<!-- 多选项、单选项公用一个 -->
<li
v-for="(ele, eIndex) in item.detailList"
:key="eIndex"
:class="{ activeLi: ele.isSelected }"
class="justify-center items-center"
@click="selectMutiple(eIndex, item.key, item.isMutiple, item)"
>
<span> {{ ele.title }}</span>
</li>
<!-- 单选项,且有日期选择框的那种 -->
<div v-if="!item.isMutiple && item.childrenType == 'rangetime'">
<el-date-picker
v-model="item.dateTime"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD HH:mm:ss"
@change="changeDate($event, item.key, item)"
/>
</div>
</ul>
</div>
</div>
</li>
</ul>
</div>
</template>
<script setup>
/***
* 筛选组件,当前支持多选、单选
* item.type (custom 单选、多选、rangetime 时间范围带时分秒、range 时间范围不带时分秒、rangenumber 数字范围)
* item.isMutiple 是否支持多选
* 筛选后返回格式{"listName1":[value,value](多选),"listName2":"value"(单选),...}
* rangenumber形式-可能为["",1]或[1,""]表示只有一个最大值或最小值
***/
// Props
defineProps({
list: {
type: Array,
default() {
return []
}
}
})
// Emit
const emit = defineEmits('resultConditon')
// Result object
const result = {}
// 选中默认项
const selectDefault = (list, isMutiple, item) => {
if (isMutiple) {
// 多选情况下,选中所有项
for (let i = 0; i < list.length; i++) {
list[i].isSelected = true
}
} else {
// 单选情况下,取消选中所有项并清空日期选择框
for (let i = 0; i < list.length; i++) {
list[i].isSelected = false
}
item.dateTime = null
}
item.defaultSelect = true
result[item.key] = ''
emit('resultConditon', result)
}
// 多选项点击事件
const selectMutiple = (index, key, isMutiple, item) => {
if (isMutiple) {
// 多选情况下,切换选中状态并更新结果对象
item.detailList[index].isSelected = !item.detailList[index].isSelected
if (!result[key]) {
result[key] = []
}
if (item.detailList[index].isSelected) {
result[key].push(item.detailList[index].value)
} else {
item.detailList[index].isSelected = false
let idx = result[key].indexOf(item.detailList[index].value)
result[key].splice(idx, 1)
}
let length = item.detailList.filter(item => item.isSelected).length
if (length === item.detailList.length || length == 0) {
item.defaultSelect = true
} else {
item.defaultSelect = false
}
console.log(result)
} else {
// 单选情况下,更新选中项并更新结果对象
item.defaultSelect = false
item.dateTime = null
result[key] = item.detailList[index].value
for (let i = 0; i < item.detailList.length; i++) {
if (index == i) {
item.detailList[i].isSelected = true
} else {
item.detailList[i].isSelected = false
}
}
}
emit('resultConditon', result)
}
// 选中日期框
const changeDate = (value, key, item) => {
const createTime = value ? [...value].join(',') : ''
result[key] = createTime
item.defaultSelect = false
for (let i = 0; i < item.detailList.length; i++) {
item.detailList[i].isSelected = false
}
if (!createTime) {
item.defaultSelect = true
}
emit('resultConditon', result)
}
</script>
<style lang="scss" scoped>
/* @use ''; 引入css类 */
.fjj-content {
.fjj-list {
row-gap: 10px;
& > li {
.label-box {
margin-right: 8px;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #818181;
padding: 8px 0;
}
.tags-list {
li {
padding: 8px 14px;
margin-right: 2px;
cursor: pointer;
span {
line-height: 14px;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #333333;
}
&.activeLi {
background: #ebf5ff;
span {
color: #2794ff;
}
}
}
}
}
}
}
</style>
以下是引入代码模块
<template>
<div class="newsInfo">
<!-- 筛选项 -->
<fjj-condition :list="menuList" @resultConditon="resultConditon" />
</div>
</template>
<script setup>
/**
* 筛选项数据
*/
const menuList = ref([
{
title: '信源类型',
type: 'custom',
key: 'siteTypes',
isMutiple: true, //多选
defaultLabel: '全选',
defaultSelect: true,
detailList: [
{
value: '6FD6F9F43DE8420',
title: '智库网站'
},
{
value: '5F4990CACF12410',
title: '新闻网站'
},
{
value: '5F4990CACF12666',
title: '社交媒体'
}
]
},
{
title: '采集时间',
type: 'custom',
key: 'createTime',
isMutiple: false, //单选
defaultLabel: '全部',
defaultSelect: true,
childrenType: 'rangetime',
detailList: [
{
title: '24h',
value: 1
},
{
title: '近三日',
value: 2
},
{
title: '最近一周',
value: 3
},
{
title: '最近一个月',
value: 4
}
]
}
])
// 获取筛选项数据
const resultConditon = obj => {
console.log(obj)
}
</script>
<style lang="scss" scoped>
/* @use ''; 引入css类 */
.newsInfo {
padding: 24px 39px 23px 40px;
}
</style>
本文来自博客园,作者:一尘子!,转载请注明原文链接:https://www.cnblogs.com/mengqc1995/p/17670233.html