Skip to content

Table表格组件

表格组件用于展示行列数据,适用于大量结构化数据的展现,以及对数据进行排序、搜索、分页、自定义操作等复杂行为。

如何使用

通过指定dataSource(一个数组)和columns来创建表格,示例如下:

html
<template>
  <a-table :dataSource="dataSource" :columns="columns" />
</template>
<script>
  export default {
    setup() {
      return {
        dataSource: [
          {
            key: '1',
            name: '胡彦斌',
            age: 32,
            address: '西湖区湖底公园1号',
          },
          {
            key: '2',
            name: '胡彦祖',
            age: 42,
            address: '西湖区湖底公园1号',
          },
        ],
        columns: [
          {
            title: '姓名',
            dataIndex: 'name',
            key: 'name',
          },
          {
            title: '年龄',
            dataIndex: 'age',
            key: 'age',
          },
          {
            title: '住址',
            dataIndex: 'address',
            key: 'address',
          },
        ],
      };
    },
  };
</script>

代码演示

  1. 基本用法:展示简单表格,最后一列包含各种操作。通过#headerCell#bodyCell插槽自定义表头和表格单元格内容。
Name AgeAddressTagsAction
John Brown32New York No. 1 Lake ParkNICEDEVELOPERInvite 一 John BrownDelete More actions
Jim Green42London No. 1 Lake ParkLOSERInvite 一 Jim GreenDelete More actions
Joe Black32Sidney No. 1 Lake ParkCOOLTEACHERInvite 一 Joe BlackDelete More actions
vue
<template>
  <a-table :columns="columns" :data-source="data">
    <template #headerCell="{ column }">
      <template v-if="column.key === 'name'">
        <span>
          <smile-outlined />
          Name
        </span>
      </template>
    </template>

    <template #bodyCell="{ column, record }">
      <template v-if="column.key === 'name'">
        <a>
          {{ record.name }}
        </a>
      </template>
      <template v-else-if="column.key === 'tags'">
        <span>
          <a-tag
            v-for="tag in record.tags"
            :key="tag"
            :color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
          >
            {{ tag.toUpperCase() }}
          </a-tag>
        </span>
      </template>
      <template v-else-if="column.key === 'action'">
        <span>
          <a>Invite 一 {{ record.name }}</a>
          <a-divider type="vertical" />
          <a>Delete</a>
          <a-divider type="vertical" />
          <a class="ant-dropdown-link">
            More actions
            <down-outlined />
          </a>
        </span>
      </template>
    </template>
  </a-table>
</template>
<script lang="ts" setup>
import { SmileOutlined, DownOutlined } from '@ant-design/icons-vue';
const columns = [
  {
    name: 'Name',
    dataIndex: 'name',
    key: 'name',
  },
  {
    title: 'Age',
    dataIndex: 'age',
    key: 'age',
  },
  {
    title: 'Address',
    dataIndex: 'address',
    key: 'address',
  },
  {
    title: 'Tags',
    key: 'tags',
    dataIndex: 'tags',
  },
  {
    title: 'Action',
    key: 'action',
  },
];

const data = [
  {
    key: '1',
    name: 'John Brown',
    age: 32,
    address: 'New York No. 1 Lake Park',
    tags: ['nice', 'developer'],
  },
  {
    key: '2',
    name: 'Jim Green',
    age: 42,
    address: 'London No. 1 Lake Park',
    tags: ['loser'],
  },
  {
    key: '3',
    name: 'Joe Black',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
    tags: ['cool', 'teacher'],
  },
];
</script>
  1. 树形数据展示:表格支持树形数据展示,当数据中有children字段时自动展示为树形表格,可通过childrenColumnName配置树形结构列名,通过indentSize控制缩进宽度。
CheckStrictly:
NameAgeAddress
John Brown sr.60New York No. 1 Lake Park
Joe Black32Sidney No. 1 Lake Park
vue
<template>
  <a-space align="center" style="margin-bottom: 16px">
    CheckStrictly:
    <a-switch v-model:checked="rowSelection.checkStrictly"></a-switch>
  </a-space>
  <a-table :columns="columns" :data-source="data" :row-selection="rowSelection" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const columns = [
  {
    title: 'Name',
    dataIndex: 'name',
    key: 'name',
  },
  {
    title: 'Age',
    dataIndex: 'age',
    key: 'age',
    width: '12%',
  },
  {
    title: 'Address',
    dataIndex: 'address',
    width: '30%',
    key: 'address',
  },
];

interface DataItem {
  key: number;
  name: string;
  age: number;
  address: string;
  children?: DataItem[];
}

const data: DataItem[] = [
  {
    key: 1,
    name: 'John Brown sr.',
    age: 60,
    address: 'New York No. 1 Lake Park',
    children: [
      {
        key: 11,
        name: 'John Brown',
        age: 42,
        address: 'New York No. 2 Lake Park',
      },
      {
        key: 12,
        name: 'John Brown jr.',
        age: 30,
        address: 'New York No. 3 Lake Park',
        children: [
          {
            key: 121,
            name: 'Jimmy Brown',
            age: 16,
            address: 'New York No. 3 Lake Park',
          },
        ],
      },
      {
        key: 13,
        name: 'Jim Green sr.',
        age: 72,
        address: 'London No. 1 Lake Park',
        children: [
          {
            key: 131,
            name: 'Jim Green',
            age: 42,
            address: 'London No. 2 Lake Park',
            children: [
              {
                key: 1311,
                name: 'Jim Green jr.',
                age: 25,
                address: 'London No. 3 Lake Park',
              },
              {
                key: 1312,
                name: 'Jimmy Green sr.',
                age: 18,
                address: 'London No. 4 Lake Park',
              },
            ],
          },
        ],
      },
    ],
  },
  {
    key: 2,
    name: 'Joe Black',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
  },
];

const rowSelection = ref({
  checkStrictly: false,
  onChange: (selectedRowKeys: (string | number)[], selectedRows: DataItem[]) => {
    console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
  },
  onSelect: (record: DataItem, selected: boolean, selectedRows: DataItem[]) => {
    console.log(record, selected, selectedRows);
  },
  onSelectAll: (selected: boolean, selectedRows: DataItem[], changeRows: DataItem[]) => {
    console.log(selected, selectedRows, changeRows);
  },
});
</script>
  1. 表头分组:通过columns[n]内嵌children渲染分组表头。
Name
OtherCompanyGender
Age
AddressCompany AddressCompany Name
StreetBlock
BuildingDoor No.
John Brown1Lake ParkC2035Lake Street 42SoftLake CoM
John Brown2Lake ParkC2035Lake Street 42SoftLake CoM
John Brown3Lake ParkC2035Lake Street 42SoftLake CoM
John Brown4Lake ParkC2035Lake Street 42SoftLake CoM
John Brown5Lake ParkC2035Lake Street 42SoftLake CoM
John Brown6Lake ParkC2035Lake Street 42SoftLake CoM
John Brown7Lake ParkC2035Lake Street 42SoftLake CoM
John Brown8Lake ParkC2035Lake Street 42SoftLake CoM
John Brown9Lake ParkC2035Lake Street 42SoftLake CoM
John Brown10Lake ParkC2035Lake Street 42SoftLake CoM
vue
<template>
  <a-table
    :columns="columns"
    :data-source="data"
    bordered
    size="middle"
    :scroll="{ x: 'calc(700px + 50%)', y: 240 }"
  />
</template>
<script lang="ts" setup>
import type { TableColumnsType } from '@design-middle-center/fuse-design-vue'
type TableDataType = {
  key: number
  name: string
  age: number
  street: string
  building: string
  number: number
  companyAddress: string
  companyName: string
  gender: string
}
const columns: TableColumnsType = [
  {
    title: 'Name',
    dataIndex: 'name',
    key: 'name',
    width: 100,
    fixed: 'left',
    filters: [
      {
        text: 'Joe',
        value: 'Joe'
      },
      {
        text: 'John',
        value: 'John'
      }
    ],
    onFilter: (value: string | number | boolean, record: TableDataType) =>
      record.name.indexOf(value as string) === 0
  },
  {
    title: 'Other',
    children: [
      {
        title: 'Age',
        dataIndex: 'age',
        key: 'age',
        width: 200,
        sorter: (a: TableDataType, b: TableDataType) => a.age - b.age
      },
      {
        title: 'Address',
        children: [
          {
            title: 'Street',
            dataIndex: 'street',
            key: 'street',
            width: 200
          },
          {
            title: 'Block',
            children: [
              {
                title: 'Building',
                dataIndex: 'building',
                key: 'building',
                width: 100
              },
              {
                title: 'Door No.',
                dataIndex: 'number',
                key: 'number',
                width: 100
              }
            ]
          }
        ]
      }
    ]
  },
  {
    title: 'Company',
    children: [
      {
        title: 'Company Address',
        dataIndex: 'companyAddress',
        key: 'companyAddress',
        width: 200
      },
      {
        title: 'Company Name',
        dataIndex: 'companyName',
        key: 'companyName'
      }
    ]
  },
  {
    title: 'Gender',
    dataIndex: 'gender',
    key: 'gender',
    width: 80,
    fixed: 'right'
  }
]
const data = [...Array(100)].map((_, i) => ({
  key: i,
  name: 'John Brown',
  age: i + 1,
  street: 'Lake Park',
  building: 'C',
  number: 2035,
  companyAddress: 'Lake Street 42',
  companyName: 'SoftLake Co',
  gender: 'M'
}))
</script>

API

  1. Table
参数说明类型默认值版本
bodyCell个性化单元格v-slot:bodyCell="{text, record, index, column}"-3.0
bordered是否展示外边框和列边框booleanfalse-
childrenColumnName指定树形结构的列名stringchildren-
columns表格列的配置描述array--
components覆盖默认的table元素object--
customFilterDropdown自定义筛选菜单,需配合column.customFilterDropdown使用v-slot:customFilterDropdown="FilterDropdownProps "-3.0
customFilterIcon自定义筛选图标v-slot:customFilterIcon="{filtered, column}"-3.0
customHeaderRow设置头部行属性Function(columns, index)--
customRow设置行属性Function(record, index)--
dataSource数据数组object[]--
defaultExpandAllRows初始时是否展开所有行booleanfalse-
defaultExpandedRowKeys默认展开的行string[]--
emptyText自定义空数据时的显示内容v-slot:emptyText-3.0
expandedRowKeys(v-model)展开的行,控制属性string[]--
expandedRowRender额外的展开行Function(record, index, indent, expanded):VNode | v-slot:expandedRowRender="{record, index, indent, expanded}"--
expandFixed控制展开图标是否固定,可选trueleftrightboolean | stringfalse3.0
expandColumnTitle自定义展开列表头v-slot-4.0.0
expandIcon自定义展开图标Function(props):VNode | v-slot:expandIcon="props"--
expandRowByClick通过点击行来展开子行booleanfalse-
footer表格尾部Function(currentPageData)|v-slot:footer="currentPageData"--
getPopupContainer设置表格内各类浮层的渲染节点,如筛选菜单(triggerNode) => HTMLElement() => TableHtmlElement1.5.0
headerCell个性化头部单元格v-slot:headerCell="{title, column}"-3.0
indentSize展示树形数据时,每层缩进的宽度,单位为pxnumber15-
loading页面是否加载中boolean|objectfalse-
locale默认文案设置,包括排序、过滤、空数据文案objectfilterConfirm: 确定
filterReset: 重置
emptyText: 暂无数据
-
pagination分页器,设为false时不展示和进行分页object | false--
rowClassName表格行的类名Function(record, index):string--
rowExpandable设置是否允许行展开(record) => boolean-3.0
rowKey表格行key的取值,可以是字符串或一个函数stringFunction(record):string'key'
rowSelection列表项是否可选择的配置项objectnull-
scroll表格是否可滚动,也可指定滚动区域的宽、高object--
showExpandColumn设置是否展示行展开列booleantrue3.0
showHeader是否显示表头booleantrue-
showSorterTooltip表头是否显示下一次排序的tooltip提示,参数类型为对象时将被设置为Tooltip的属性boolean | Tooltip propstrue3.0
size表格大小large | middle | smalllarge-
sortDirections支持的排序方式Array['ascend', 'descend']-
sticky设置粘性头部和滚动条boolean | {offsetHeader?: number, offsetScroll?: number, getContainer?: () => HTMLElement}-3.0
summary总结栏v-slot:summary-3.0
tableLayout表格元素的table-layout属性- | 'auto' | 'fixed'无固定表头/列或使用column.ellipsis时,默认值为fixed1.5.0
title表格标题Function(currentPageData)|v-slot:title="currentPageData"--
transformCellText数据渲染前再次改变数据,一般用于空数据的默认配置,可通过ConfigProvider全局统一配置Function({ text, column, record, index }) => any-1.5.4
  1. 事件
事件名称说明回调参数
change分页、排序、筛选变化时触发Function(pagination, filters, sorter, { action, currentDataSource })
expand点击展开图标时触发Function(expanded, record)
expandedRowsChange展开的行变化时触发Function(expandedRows)
resizeColumn拖动列时触发Function(width, column)
  1. Column:列描述数据对象,是columns中的一项
参数说明类型默认值版本
align设置列的对齐方式left | right | centerleft-
colSpan表头列合并,设置为0时不渲染number--
customCell设置单元格属性Function(record, rowIndex, column)-column add from 3.0
customFilterDropdown启用v-slot:customFilterDropdown,优先级低于filterDropdownbooleanfalse3.0
customHeaderCell设置头部单元格属性Function(column)--
customRender生成复杂数据的渲染函数Function({text, record, index, column}) {}--
dataIndex列数据在数据项中对应的路径,支持通过数组查询嵌套路径string | string[]--
defaultFilteredValue默认筛选值string[]-1.5.0
filterResetToDefaultFilteredValue点击重置按钮时,是否恢复默认筛选值booleanfalse3.3.0
defaultSortOrder默认排序顺序ascend | descend--
ellipsis超过宽度自动省略,暂不支持与排序筛选一起使用,设置为true{ showTitle?: boolean }时,表格布局变为tableLayout="fixed"boolean | { showTitle?: boolean }false3.0
filterDropdown自定义筛选菜单VNode | (props: FilterDropdownProps) => VNode--
filterDropdownOpen控制自定义筛选菜单是否可见boolean--
filtered标识数据是否经过过滤,筛选图标会高亮booleanfalse-
filteredValue筛选的受控属性,外界可用此控制列的筛选状态string[]--
filterIcon自定义filter图标VNode | ({filtered: boolean, column: Column}) => vNodefalse-
filterMode指定筛选菜单的用户界面'menu' | 'tree''menu'3.0
filterMultiple是否多选booleantrue-
filters表头的筛选菜单项object[]--
filterSearch筛选菜单项是否可搜索boolean | function(input, filter):booleanfalseboolean:3.0 function:3.3.0
fixed列是否固定,可选true(等效于left)、'left''right'boolean|stringfalse-
keyVue需要的keystring--
maxWidth拖动列最大宽度number-3.0
minWidth拖动列最小宽度number503.0
resizable是否可拖动调整宽度boolean-3.0
responsive响应式breakpoint配置列表Breakpoint []-3.0
rowScope设置列范围row | rowgroup-4.0
showSorterTooltip表头显示下一次排序的tooltip提示,覆盖table中的showSorterTooltipboolean | Tooltip propstrue-
sortDirections支持的排序方式Array['ascend', 'descend']1.5.0
sorter排序函数Functionboolean-
sortOrder排序的受控属性string--
title列头显示文字string--
width列宽度stringnumber-
onFilter本地模式下,确定筛选的运行函数Function--
onFilterDropdownOpenChange自定义筛选菜单可见变化时调用function(open) {}-4.0
  1. ColumnGroup
参数说明类型默认值
title列头显示文字stringslot
  1. pagination:分页的配置项
参数说明类型默认值
position指定分页显示的位置Array['bottomRight']
  1. rowSelection:选择功能的配置
参数说明类型默认值版本
checkStrictlycheckable状态下节点选择完全受控booleantrue3.0
columnTitle自定义列表选择框标题stringVNode-
columnWidth自定义列表选择框宽度stringnumber-
fixed把选择框列固定在左边boolean--
getCheckboxProps选择框的默认属性配置Function(record)--
hideDefaultSelections去掉『全选』『反选』两个默认选项booleanfalse-
hideSelectAll隐藏全选勾选框与自定义选择项booleanfalse3.0
preserveSelectedRowKeys数据删除时保留选项的keyboolean-3.0
selectedRowKeys指定选中项的key数组string[][]-
selections自定义选择项配置项,设为true时使用默认选择项object[]booleantrue
type多选/单选stringcheckbox-
onChange选中项发生变化时的回调Function(selectedRowKeys, selectedRows)--
onSelect用户手动选择/取消选择某列的回调Function(record, selected, selectedRows, nativeEvent)--
onSelectAll用户手动选择/取消选择所有列的回调Function(selected, selectedRows, changeRows)--
onSelectInvert用户手动选择反选的回调Function(selectedRows)--
onSelectNone用户清空选择的回调function()-3.0
  1. scroll
参数说明类型默认值
scrollToFirstRowOnChange分页、排序、筛选变化后是否滚动到表格顶部boolean-
x设置横向滚动stringnumber
y设置纵向滚动stringnumber
  1. selection:自定义选择配置项
参数说明类型默认值
keyVue需要的keystring-
text选择项显示的文字stringVNode
onSelect选择项点击回调Function(changeableRowKeys)-
  1. FilterDropdownProps
typescript
interface FilterDropdownProps {
  prefixCls: string;
  setSelectedKeys: (selectedKeys: Key[]) => void;
  selectedKeys: Key[];
  confirm: (param?: FilterConfirmProps) => void;
  clearFilters?: (param?: FilterResetProps) => void;
  filters?: ColumnFilterItem[];
  visible: boolean;
  column: ColumnType;
}
interface FilterConfirmProps {
  closeDropdown: boolean;
}
interface FilterResetProps {
  confirm?: boolean;
  closeDropdown?: boolean;
}

注意

在Table中,dataSourcecolumns里的数据值都需指定key值。若dataSource数据没有key属性,务必使用rowKey指定数据列的主键,否则控制台会提示缺少key,表格组件也可能出现错误。

FAQ(续)

  1. 表格过滤时会回到第一页?:前端过滤时,由于条目总数减少,可能导致总页数小于筛选前的当前页数。为防止当前页面无数据,默认会返回第一页。若使用远程分页且需要保持当前页面,可手动控制当前页面不变。
  2. 表格分页为何会出现size切换器?:自3.0起,Pagination在total大于50条时,默认显示size切换器以提升用户交互体验。若不需要该功能,可通过设置showSizeChangerfalse来关闭。
  3. 固定列穿透到最上层该怎么办?:固定列通过z - index属性悬浮于非固定列之上,当在Table上放置遮罩层时,可能出现固定列被透过的情况。为遮罩层设置更高的z - index值,即可覆盖固定列。