vue3.0 + TS + AntD 项目开发学习笔记:table 的使用和问题

43 阅读3分钟

Table 列表是前端开发经常用到的组件框架,Antd Table 组件的基本用法参考官网,代码如下:

<template>
  <a-table :dataSource="dataSource" :columns="columns" />
</template>

dataSource 是列表数据,为数组格式,columns 是表头数据,也为数组格式,范例如下:

dataSource: [
          {
            key: '1',
            name: '胡彦斌',
            age: 32
          },
          {
            key: '2',
            name: '胡彦祖',
            age: 42
          },
        ],

columns: [
          {
            title: '姓名',
            dataIndex: 'name',
            key: 'name',
          },
          {
            title: '年龄',
            dataIndex: 'age',
            key: 'age',
          }
        ]

columns 的 key 值要与 datasource 的键值对应。在项目开发时,往往要对表头 columns 做处理,实现一些特定的功能,比如筛选,排序等。

columns: [
          {
            title: '姓名',
            dataIndex: 'name',
            key: 'name',
            sorter: true
          },
          {
            title: '年龄',
            dataIndex: 'age',
            key: 'age',
            filters: [{
                text: '32',
                value: '0'
            },{
                text: '42',
                value: '1'
            }]
          }
        ]

sorter 设置为 true, 代表这列数据可以排序,设置 filters 表示这列数据可筛选。 真正在项目中用会更为复杂一点,数据是网络请求得到的,而不是对本地数据做简单的排序和筛选,需要请求网络接口。筛选的数组也是动态展示的。截取部分项目代码如下:

// 定义 table 表头, 计算属性,根据不同状态,变更 table 表头
const columns = computed(() => {
    const sorted = useTrackingStore().tableSorted || {};
    const filtered = useTrackingStore().tableFiltered || {};
    // 时间为降序descend, 其它没要求, 用升序ascend
    var arr = ref([
        {
            title: t('tracking.common.customer'),
            dataIndex: "customerChname",
            key: 'customerChname',
            sorter: !useMasterStore().trackingMasterSearchData ?? true,
            sortOrder: sorted.columnKey === 'customerChname' && sorted.order,
            sortDirections: ["ascend"],
            resizable: true,
            width: NaN
        },
        {
            title: t('tracking.common.owner'),
            dataIndex: "owner",
            key: 'owner',
            filters: useUserStore().selectedDepartment?.[0]?.allUsers?.map((el: { egname: any; id: any }) => {
                return { text: el.egname, value: el.id }
            }) ?? [],
            filteredValue: filtered.owner || null,
            filterSearch: true,
            resizable: true,
            width: NaN
            // minWidth: 150,
        },
        {
            title: "AMT($)",
            dataIndex: "amt",
            key: 'amt',
            resizable: true,
            width: NaN
        }
    ]);
    var lastDate = ""
    const array = ref()
    switch (useTrackingStore().tabStatus) {
        case "Alive":
            lastDate = t('tracking.table.createAt');
            array.value = arr.value.filter((item: any) => item.dataIndex !== "amt");
            break;
        case "MP":
            lastDate = "MP " + t('tracking.common.date');
            array.value = arr.value
            break;
    }
    array.value[array.value.length - 1].title = lastDate
    return array.value
});

代码中的 sorter 是动态的,有的情况不允许排序,filters 也是变量数据。代码中还用到 switch 方法对表头进行过滤操作,项目要求不同页签下的表头是不一样的。这里定义变量 arr 要使用响应式数据,这样切换页签的时候不会出现异常,如果使用非响应数据有可能会出现表头错位的问题。 table 组件更复杂的使用,部分代码如下:

<a-table class="table-list" :dataSource="dataSource?.list" :columns="columns" :pagination="pagination"
  :rowClassName="getRowBackground" :row-selection="rowSelection"  :rowKey="(record: any) => record?.componentId" @change="onChange" :customRow="customRow" />
  • :rowClassName="getRowBackground" 设置行样式, 在使用行样式的时候 css 不能设置 scoped, 不然行样式会失效。
// js 代码
const getRowBackground = (record: any) => {
    if (record.isTransfer) {
        return "is-transfer"
    } else {
        return ""
    }
}
css 代码
<style>
.is-transfer {
    color: rgb(27, 27, 27);
    font-weight: 520;
    background-color: #FFFFBF;
}
</style>
  • :rowKey="(record: any) => record?.componentId" 这条语句设置表格行 key 的取值,保证唯一性,如果不加这条语句,也会造成行样式错乱。

  • :row-selection="rowSelection" 列表项是否可选择,通过 onSelectChange 方法获取选中的行信息,通过选中行信息可以实现元件列表的批量操作,如更新元件状态,更新元件进展和转交元件。

const rowSelection = computed(() => {
    if (isSelect.value) {
        return {
            selectedRowKeys: unref(selectedRowKeys),
            onChange: onSelectChange,
            getCheckboxProps: (record: IComponent) => ({
                disabled: record.isTransfer === true,
                name: record.customerCode,
            })
        }
    } else {
        return null
    }
})
/**
 *  当批量选中行时调用,并向父组件发送 selectedRowKeys 事件
 */
const onSelectChange = (changableRowKeys: string[], selectedRows: any) => {
    selectedRowKeys.value = changableRowKeys
    emit('selectedRowKeys', changableRowKeys, JSON.parse(JSON.stringify(selectedRows)));
};
  • @change = "onChange" 分页、排序、筛选变化时触发,获取变化的参数,调用 api 请求列表数据。
// 分页、排序、筛选变化时触发
const onChange = (pagination: any, filters: any, sorter: any) => {
    emit('onChange', pagination, filters, sorter)
}
  • :customRow="customRow" 是行事件,也是 table 组件用的最多的 api, 返回双击行事件 onDblclick,双击行做相应的操作。
// js 部分
/**
 *  自定义行事件
 */
const customRow = (record: any, index: any) => {
    return {
        // 双击行事件, 弹出专案详情对话框
        onDblclick: async () => {
            getDetail(record)
        }
    }
}