前端Vue技术记录Vue 3.0/多条件联动筛选业务设计
Mintal概述
当业务代码中,出现多种筛选并且筛选之间需要互相关联筛选的时候,正确的做法是:
将所有的筛选条件都封装成一个对象,包含N个筛选条件,默认值则是筛选框的默认值
所有的筛选框都应绑定同一个事件,将他们的值赋值进入“筛选对象”中
然后封装一个公共的“筛选方法”,将“筛选对象”中所有的筛选条件逐个筛选。
最终返回符合所有条件的数据
不论“筛选对象”中的哪一个值变化时,都将触发整个“筛选对象”的筛选。
这样设计的话,可以大大降低联合筛选的代码复杂性,即便后期有新筛选条件加入,也只需要修改“筛选对象”与“筛选方法”,无非就是加一个条件判断
封装筛选条件对象
将所有的筛选条件封装成一个统一的对象(例如 filterObject
),每个筛选条件作为该对象的一个属性。
这些属性的默认值应与对应筛选框的初始默认值保持一致。
统一绑定筛选事件
所有的筛选框组件应绑定同一个事件处理器,用于监听筛选条件的变化。在事件触发时,更新 filterObject
中对应筛选条件的值,以保证筛选状态的统一性。
封装公共筛选方法
设计并封装一个通用的筛选方法,例如 applyFilters
,用于处理 filterObject
中的所有筛选条件:
- 遍历
filterObject
的每个属性,并将其作为筛选规则。
- 根据这些条件,逐步过滤原始数据集合,最终返回符合所有条件的筛选结果。
统一触发筛选
无论 filterObject
中的哪一个属性值发生变化,都应触发统一的筛选逻辑。这种机制确保每次筛选的结果始终是最新且精准的,且无需额外关注具体条件的来源。
可扩展性设计
当需要新增筛选条件时,只需在 filterObject
中添加新属性,并在 applyFilters
方法中增加相关的筛选逻辑,无需改动核心结构或现有筛选条件的代码。
示例代码(仅为示例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| <template> <div> <el-row :gutter="20" class="filter-row"> <el-col :span="8"> <el-input v-model="filterObject.search" placeholder="请输入关键字" clearable > <template #prefix> <el-icon><Search /></el-icon> </template> </el-input> </el-col>
<el-col :span="8"> <el-select v-model="filterObject.type" placeholder="请选择类型" clearable > <el-option label="全部" value="all" /> <el-option label="2D" value="2D" /> <el-option label="3D" value="3D" /> </el-select> </el-col>
<el-col :span="8"> <el-checkbox-group v-model="filterObject.detectionType"> <el-checkbox label="工程" /> <el-checkbox label="设计" /> <el-checkbox label="建筑" /> <el-checkbox label="工业" /> </el-checkbox-group> </el-col> </el-row>
<el-row> <el-col :span="24"> <el-card> <h3>筛选结果:</h3> <el-table :data="applyFilters" style="width: 100%"> <el-table-column prop="name" label="名称" /> <el-table-column prop="type" label="类型" /> <el-table-column label="标签" v-slot="scope" > {{ scope.row.tags.join(', ') }} </el-table-column> </el-table> </el-card> </el-col> </el-row> </div> </template>
<script lang="ts"> import { reactive, computed, defineComponent } from "vue"; import { ElMessage } from "element-plus"; import { Search } from "@element-plus/icons-vue";
export default defineComponent({ components: { Search, }, setup() { const dataList = [ { id: 1, name: "CAD图纸1", type: "2D", tags: ["工程", "设计"] }, { id: 2, name: "CAD图纸2", type: "3D", tags: ["建筑", "工程"] }, { id: 3, name: "CAD图纸3", type: "2D", tags: ["工业", "设计"] }, ];
const filterObject = reactive({ search: "", type: "all", detectionType: [] as string[], });
const applyFilters = computed(() => { const result = dataList.filter((item) => { const matchType = filterObject.type === "all" || item.type === filterObject.type;
const matchSearch = filterObject.search ? item.name.includes(filterObject.search) : true;
const matchDetection = filterObject.detectionType.length ? filterObject.detectionType.every((tag) => item.tags.includes(tag)) : true;
return matchType && matchSearch && matchDetection; });
if (result.length === 0) { ElMessage.info("没有符合条件的数据!"); }
return result; });
return { filterObject, applyFilters, }; }, }); </script>
|