element-plus封装表格列筛选方法,列表排序、筛选联动

461 阅读3分钟

效果展示

渲染出来的表格

表格内容展示渲染


数据是无序的,这里表格的筛选列表采用递增排序,若是字符则按照Unicode码位值排序

表格筛选列表递增排序


这里筛选身高是170的

筛选前

筛选身高是170的-筛选前

筛选后

筛选身高是170的-筛选后

并且其它的筛选列表也会根据当前数据联动变化,这里以地区为例

地区的筛选列表根据数据联动

当对其它列也做筛选操作,所有的筛选列表都会跟着联动,这里对身高和地区都做筛选,年龄的筛选列表更新

多个筛选条件联动

页面使用

给el-table绑定 filter-change 事件,该事件在操作表格筛选功能时触发,会返回当前筛选条件

    <template>
        <el-table
            :data="tableData" 
            @filter-change="filterChange"
            height="400"
            stripe 
            border
        >
            <el-table-column 
                v-for="item in columns"
                :label="item.label"
                :prop="item.prop"
                :width="item.width"
                :filters="item.filters"
                :filter-method="item.filterMethod"
                :columnKey="item.columnKey"
            >
            </el-table-column>
        </el-table>
    </template>
    <script setup lang="ts">
    import { onMounted, ref } from 'vue';
    import { filterColumn } from './utils.ts'
    import { columns } from "./data.ts";
    const tableData = ref([])
    let filterChange: (newFilters: any) => void = (a) => {}
    const onQuery = async () => {
        // 这里模拟数据
        tableData.value = [
            {
                code: 1003,
                age: 19,
                address: '天津',
                height: 180
            },
            {
                code: 1004,
                age: 20,
                address: '上海',
                height: 170
            },
            {
                code: 1001,
                age: 18,
                address: '北京',
                height: 170
            },
            {
                code: 1002,
                age: 19,
                address: '北京',
                height: 166
            },
        ]
        // 这里使用筛选方法,返回的filterChange函数,直接赋值绑定到el-table上
        const filterObj = filterColumn(columns.value, tableData.value, true)
        filterChange = filterObj.filterChange
    }
    onMounted(() => {
        onQuery()
    })
    </script>

表格列数据

data.ts 文件中导出的表格列数据:

  1. filtersfilterMethod 为筛选功能必须的属性;
  2. 设置 columnKey 为当前列的 prop 字段,用来在表格 filter-change 事件触发后,判断当前是做的哪一列的筛选;
  3. columns 的数据必须是响应式数据,否则表格的筛选列表不会有内容
    import { ref } from 'vue'

    export const columns = ref([
        {
            label: "编号",
            prop: "code",
            width: 100,
            filters: [],
            filterMethod: (value, row, column) => row.code == value,
            columnKey: "code"
        },
        {
            label: "年龄",
            prop: "age",
            width: 100,
            filters: [],
            filterMethod: (value, row, column) => row.age == value,
            columnKey: "age"
        },
        {
            label: "地区",
            prop: "address",
            width: 100,
            filters: [],
            filterMethod: (value, row, column) => row.address == value,
            columnKey: "address"
        },
        {
            label: "身高",
            prop: "height",
            width: 100,
            filters: [],
            filterMethod: (value, row, column) => row.height == value,
            columnKey: "height"
        },
    ])

表格列筛选方法

utils.ts 文件中导出的方法

    /**
     * 表格列筛选方法
     * @param columns 表格绑定的列渲染数据
     * @param tableData 表格数据
     * @param isSort 是否排序,默认true,递增排序。
     * @returns filterChange el-table筛选功能触发函数
     * 注:实现表格列筛选功能,传递的 columns 要是响应式数据。
     */
    export const filterColumn = (columns: any[], tableData: Array<any>, isSort = true ) => {

        // // 为每一列添加筛选标识,但是发现筛选函数触发后,筛选标识有时候会被清空,所以将筛选标识写在columns中
        // columns.forEach((v) => {
        //   v.columnKey = v.prop
        // })

        // 生成表格筛选功能所需的内容对象
        const generateFilters = (tData) => {
            // 1. 先清空原来columns数组中filters的内容
            columns.forEach((v) => {
            if (v.filters) {
                v.filters.splice(0)
            }
            });
            // 2. 遍历表格列数组,对有filters属性的这一项,添加表格筛选功能所需的内容对象
            columns.forEach((a) => {
                if (a.filters) {
                tData.forEach((item) => {
                        if (!a.filters.some((i) => i.text === item[a.prop])) {
                            a.filters.push({ text: item[a.prop], value: item[a.prop] })
                        }
                    });
                }
            });
            // 3. 对filters属性的数组进行排序
            if (isSort) {
            columns.forEach((a) => {
                if (a.filters.length > 0) {
                if (isNaN(+a.filters[0].value)) {
                    a.filters.sort((s, f) => {
                    if (s.value > f.value) {
                        return 1
                    } else if (s.value < f.value) {
                        return -1
                    } else {
                        return 0
                    }
                    })
                } else {
                    a.filters.sort((s, f) => {
                    return +s.value - +f.value
                    })
                }
                }
            })
            }
        }
        generateFilters(tableData)

        // 筛选功能触发后,找出符合条件的表格数据
        let filterData = {}
        const filterChange = (curFilters) => {
            Object.assign(filterData, curFilters)
            const filterTableData = tableData.flatMap(item => {
            return Object.keys(filterData).every(key => filterData[key].length === 0 || filterData[key].includes(item[key])) ? item : []
            })
            console.log('filterTableData', filterTableData)
            generateFilters(filterTableData)
        }

        return {
            filterChange
        }
    }