Vue3 + Element Plus 表格多字段组合排序

1,171 阅读2分钟

一、需求要的效果

image.png

二、直接开干

找个喜欢的地方添加个ts类型

这里定义的是obj类型的,后面请求拦截里面把他转成string,后端才能正常接收

/**
 * 搜索通用参数
 */
export interface SearchParams {
    orderByStr?: {
        [key: string]: 'asc' | 'desc'
    }
}

改一下请求拦截

// 请求拦截器
service.interceptors.request.use(
    // 在发送请求之前做一些事情
    (config) => {
        ...
    
        // 处理自定义表格组合排序参数
        if (config.params?.orderByStr) {
            config.params.orderByStr = JSON.stringify(config.params.orderByStr)
        }

        return config
    },
    ...
)

封装排序相关的函数

新建文件 src\composables\use-table-sort.ts

/**
 * 表格数据自定义排序通用方法
 */

export default function () {
    /**
     * 当前点击的表头字段名
     */
    let currentClickProperty = ''

    /**
     * 手动处理排序
     * @param param0 默认回调参数
     * @param searchForm 搜索表单
     * @param getList 获取列表的函数
     */
    const handleSortChange = ({ prop, order }: any, searchForm: any, getList: any) => {
        if (order) {
            if (!searchForm.orderByStr) {
                searchForm.orderByStr = {}
            }

            order === 'ascending' && (order = 'asc')
            order === 'descending' && (order = 'desc')

            searchForm.orderByStr[prop] = order

            // console.log('orderArray', searchForm)
            getList()
        } else {
            /**
             * 取消排序时,column, prop, order 都是 null,无法判断是哪一列取消了排序
             * 所以要等 @header-click 事件执行完成,再用当前点击的表头字段名来判断是哪一列
             */
            setTimeout(() => {
                // 清除取消排序的列
                if (searchForm.orderByStr) {
                    delete searchForm.orderByStr[currentClickProperty]
                }

                // console.log('orderArray', searchForm)
                getList()
            }, 0)
        }
    }

    /**
     * 点击表头回调
     * @param column 当前点击列的对象
     */
    const headerClick = (column: any) => {
        // 把当前点击的表头字段名存起来,后面取消列的排序会用到
        currentClickProperty = column.property
    }

    /**
     * 处理表头样式
     * @param param0 默认回调参数
     * @param searchForm 搜索表单
     */
    const handleHeaderCellClass = ({ column }: any, searchForm: any) => {
        /**
         * 遍历更新每一列的排序状态
         * 要用setTimeout等取消列排序的操作执行完成,才去更新表头样式
         */
        setTimeout(() => {
            if (searchForm.orderByStr) {
                for (const key in searchForm.orderByStr) {
                    if (key === column.property) {
                        let order: any = searchForm.orderByStr[key]
                        order === 'asc' && (order = 'ascending')
                        order === 'desc' && (order = 'descending')

                        column.order = order
                    }
                }
            }
        }, 0)
    }

    return {
        handleSortChange,
        headerClick,
        handleHeaderCellClass,
    }
}

然后就可以直接在vue组件里面用了

导入封装的函数

import UseTableSort from '@/composables/use-table-sort'

// 表格自定义组合排序
const { handleSortChange, headerClick, handleHeaderCellClass } = UseTableSort()

el-table 加上 :header-cell-class-name @sort-change @header-click

<el-table
    :header-cell-class-name="(params: any) => handleHeaderCellClass(params, searchForm)"
    @sort-change="(params: any) => handleSortChange(params, searchForm, getList)"
    @header-click="headerClick"
>

el-table-column 加上 sortable="custom"

<el-table-column label="教材名称" prop="productName" min-width="100" sortable="custom" />

提交的参数长这样

{
    ...
    orderByStr: {
        productName: 'asc',
        pressName: 'desc',
        stockNumber: 'asc',
        price: 'asc',
    },
    ...
}

三、最后

有几个变量命名感觉不是很好,但是懒得改了,后面再优化吧[狗头]

溜了溜了...

ceeb653ely8gy03rc4a70j20da0d3753.jpg