优雅的数组多条件动态筛选

在此之前,我相信很多时候开发都会遇到这样的需求:一组条件,一个列表,多条件组合,列表显示不同的结果。
以前在我做mes系统的时候,这些事情都是交给后端去做的,因为业务需求需要显示实时最新的数据结果,
所以前端把条件通过post请求传给服务端,服务给出最新的结果。
那时候我好奇的问过后端的同事,是怎么实现这种条件判断然后去做查询,答案是if判断,
如果这种事放在前端来做,那估计通常是这样的

if(conditionA && conditionB && !conditionC)
{
    
    
	this.tableData=dataSource.filter(ele=>{
    
    ele.propertyA==conditionA  && ele.propertyB==conditionB && ele.propertyC!=conditionC)
}
else if(conditionA && !conditionB && conditionC)
{
    
    
	//...一些操作
}
else if(!conditionA && conditionB && conditionC)
{
    
    
	//...一些操作
}
else .......

基本上最坏的情况就是这样,假设有3个条件,那就会有8种不同条件判断。
abc
ab!c
a!bc
a!b!c
!abc
!a!bc
!ab!c
!a!b!c
好嘛,也就3个条件,8个就8个吧。
有的人就会这样傻乎乎的把情况列出来然后写8个判断
但是条件如果多起来,这就好玩了
这得有多少相似代码?实现这么个筛选可能就得成百上千行?
这我想想就头疼,写的时候头疼,日后维护头更疼
为了避免这种尴尬的情况,那必须优雅一点。
一开始我也自己去思考过,如何去实现低代码高质量
可惜我太菜了,没想出来,最后还是看到某位大佬写的…
下面的这串代码最初版本似乎是爆栈上某位大佬写的(呃…时间有点久,忘了)

export function multiFilter(array, filters) {
    
    
    const filterKeys = Object.keys(filters)
        // 过滤所有元素传递标准
    return array.filter((item) => {
    
    
        // 动态验证所有的过滤标准
        return filterKeys.every((key) => {
    
    
            //忽略当过滤器是空的
            if (!filters[key] || !filters[key].length) return true
                 return !!~filters[key].indexOf(item[key])
        })
    })
}

这串代码可以说
在这里插入图片描述
既然大佬都出手了,那我们这些菜鸡直接用就完事了,还费那么多头发干啥?
不过要注意的是方法传入的filters是一个对象,算是需要用到的筛选条件的组合,
但是每个属性也是个数组并且数组只能有一个元素。
使用vue+element UI 大概就可以这样

<template>
    <div class="container">
        <div class="filter_box">
            <el-select v-model="filterOption.workYear" placeholder="工龄" clearable @change="filterList" multiple :multiple-limit="1">
                <el-option
                    v-for="(item, index) in wyOpt"
                    :key="index"
                    :label="item"
                    :value="item"
                >
                </el-option>
            </el-select>
            <el-select v-model="filterOption.age" placeholder="年龄" clearable @change="filterList" multiple :multiple-limit="1">
                <el-option v-for="(item, index) in ageOpt" :key="index" :label="item.label" :value="item.value"> </el-option>
            </el-select>
            <el-select v-model="filterOption.dept" placeholder="部门" clearable @change="filterList" multiple :multiple-limit="1">
                <el-option v-for="(item, index) in deptOpt" :key="index" :label="item.label" :value="item.value"> </el-option>
            </el-select>
        </div>
        <div class="table_box">
            <el-table :data="datalist">
                <el-table-column prop="name" label="姓名"></el-table-column>
                <el-table-column prop="age" label="年龄"></el-table-column>
                <el-table-column prop="gender" label="性别"></el-table-column>
            </el-table>
        </div>
    </div>
</template>

js部分

data(){
    
    
	return{
    
    
	 filterOption: {
    
    
	        age: [],
	        name: [],
	        gender: [],
	        workType: [],
	        workYear: [],
	        dept:[]
	      },
	      ageOpt: [],
	      deptOpt:[{
    
    label:'研发',value:'dev'},{
    
    
	        label:'市场',value:'market'
	      }],
	      wyOpt:[1,2,3,4,5],
	      },
	      //源数据
	       source:[],
	       datalist: []
	}
      methods: {
    
    
    filterList (e) {
    
    
      this.datalist = multiFilter(this.source, this.filterOption)
    }
  },

在这里插入图片描述
这里仅当demo举例子,所以就偷个懒用element的多选下拉框,但是只允许选择一个,其他模样的筛选控件也是一个道理
v-model直接绑定到filterOption,change事件直接绑定同一个。
这样就简单实现动态条件筛选了,而且也没有辣么多的代码,一句话搞定
另外补充一下,上述multiFilter方法其实存在点问题,有点类似“模糊筛选”。
举个例子,你筛选条件是’滞后’,但是数据中的字段有:‘滞后’,‘严重滞后’
那么就会把‘滞后’,‘严重滞后’都筛选出来,因为用的是indexOf()
根据我的业务需要,我稍作修改

export function multiFilter(array, filters) {
    
    
    const filterKeys = Object.keys(filters)
        // 过滤所有元素传递标准
    return array.filter((item) => {
    
    
        // 动态验证所有的过滤标准
        return filterKeys.every((key) => {
    
    
            //忽略当过滤器是空的
            if (!filters[key] || !filters[key].length) return true
              //  return !!~filters[key].indexOf(item[key])
            return filters[key] == item[key]
        })
    })
}

这样就是准确结果
.
.
.
.

如有错误,欢迎大佬赐教(__)

猜你喜欢

转载自blog.csdn.net/m0_38136631/article/details/126727301