vxe-table动态列筛选以及筛选项动态变化的问题及解决
作者:吃面必吃蒜
这篇文章主要介绍了vxe-table动态列筛选以及筛选项动态变化的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
vxe-table动态列筛选以及筛选项动态变化
需求场景
- table 的列是由接口动态返回的;
- 列的筛选项就是数据的值,比如【姓名】这个字段总共有三个值,那么姓名这一列的筛选项就是这三个值本身;
- 当有一列筛选后,其他列的筛选项也要动态变化。
vxe-table 版本:4.9.14
完整代码
vue template 部分:
<vxe-table ref="vxeTableRef" :data="state.tableData" height="100%" border @filter-change="handleFilterChange" > <vxe-column v-for="colOpt in columnsOptions" :key="colOpt.field" :field="colOpt.field" :title="colOpt.title" align="center" resizable sortable :filters="colOpt.filters" :filter-method="colOpt.filterMethod" /> </vxe-table>
script 部分:
<script setup lang="ts"> // 其他代码 const vxeTableRef = ref(); const handleSearch = () => { // 获取table数据部分的逻辑 API(params).then((res: any) => { // ... state.tableData = data || []; if (state.tableData.length > 0) { // 在数据加载后重置所有筛选 nextTick(() => { if (vxeTableRef.value) { vxeTableRef.value.clearFilter(); } }); } }); } // 下面是处理列筛选的逻辑 // 获取筛选选项 const getColumnFilters = (column: string) => { // 使用 Map 来提高性能 const uniqueMap = new Map(); for (const row of state.tableData) { const value = row[column]; if (!uniqueMap.has(value)) { uniqueMap.set(value, { label: value == null || value == "" ? "(空)" : String(value), value: value, checked: false }); } } return Array.from(uniqueMap.values()); }; // 创建筛选方法 const createFilterMethod = (column: string) => { return ({ value, row }: { value: any; row: any }) => { const cellValue = row[column]; // 处理空值的情况 if (value === null || value === "") { return cellValue === null || cellValue === ""; } // 如果单元格值是数字,进行数字比较 if (typeof cellValue === "number") { return cellValue === Number(value); } // 默认进行字符串比较 return String(cellValue) === String(value); }; }; // 数据是异步加载的,使用计算属性来处理列配置 const columnsOptions = computed(() => { return state.columns.map(col => ({ field: col, title: col, filters: getColumnFilters(col), filterMethod: createFilterMethod(col) })); }); // 处理筛选变化 const handleFilterChange = (params: any) => { // 获取当前表格中可见的行数据 const { filterList } = params; // 如果没有筛选项,就刷新 if (!filterList || filterList.length === 0) { handleSearch(); } // 筛选已经应用,获取处理后的可见数据 const visibleData = vxeTableRef.value?.getTableData().visibleData || []; // 获取当前被筛选的列,避免修改它们的筛选项 const filteredColumns = new Set(filterList.map((item: any) => item.field)); // 更新筛选状态 nextTick(() => { // 只更新未被筛选的列 state.columns.forEach(column => { // 跳过当前正在筛选的列 if (filteredColumns.has(column)) return; // 为此列生成新的筛选选项,但仅从可见数据中获取 const uniqueMap = new Map(); for (const row of visibleData) { const value = row[column]; if (!uniqueMap.has(value)) { uniqueMap.set(value, { label: value == null || value === "" ? "(空)" : String(value), value: value, checked: false }); } } // 更新此列的筛选项 if (vxeTableRef.value) { vxeTableRef.value.setFilter(column, Array.from(uniqueMap.values())); } }); }); }; </script>
里面关键的一个点在于,vxe-table 筛选后的展示数据跟我们的源数据是分开的,所以筛选触发的事件中,我们应该拿 visibleData 来做筛选项的动态处理。
由于逻辑可复用,所以记录一下,需要用的时候直接copy就好了。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。