# Table

A data table. Supports sorting (controlled / uncontrolled), column filtering, column resizing by dragging, multi-level headers (children nested without limit), and fixed columns; setting height enables virtual scrolling (rowHeight must match the actual row height).

Table
<template>
  <div style="max-width: 760px">
    <p class="demo-note">size="small" + maxHeight + 默认排序(defaultSortProp/defaultSortOrder)+ 筛选</p>
    <LhTable
      :data="rows"
      :columns="columns"
      size="small"
      stripe
      border
      :max-height="200"
      row-key="name"
      default-sort-prop="dynasty"
      default-sort-order="asc"
      :default-filtered-values="{ dynasty: ['宋'] }"
    >
      <template #price="{ value }">
        <span style="color: var(--lh-primary-color); font-weight: 600">{{ value }}</span>
      </template>
    </LhTable>
    <p class="demo-note">「朝代」列默认升序且预筛「宋」;表头筛选按钮可改条件。</p>
    <p class="demo-note" style="margin-top: 16px">嵌套表头(children)+ resizable 拖宽 + formatter + 自定义 sorter</p>
    <LhTable :data="rows2" :columns="groupColumns" border :height="180" :row-height="40" :sorter="dynastySorter">
      <template #price="{ value }">
        <span style="color: var(--lh-primary-color); font-weight: 600">{{ value }}</span>
      </template>
    </LhTable>
    <p class="demo-note">「流传」列用 formatter 格式化为「宫藏/民间」;「估价」列可拖宽(resizable)。</p>
  </div>
</template>

<script>
export default {
  data: () => ({
    rows: [
      { name: '溪山行旅图', dynasty: '宋', price: 1800 },
      { name: '富春山居图', dynasty: '元', price: 2600 },
      { name: '千里江山图', dynasty: '宋', price: 3200 },
      { name: '清明上河图', dynasty: '宋', price: 1500 },
      { name: '韩熙载夜宴图', dynasty: '五代', price: 2100 },
    ],
    rows2: [
      { name: '溪山行旅图', dynasty: '宋', provenance: '宫藏', price: 1800 },
      { name: '富春山居图', dynasty: '元', provenance: '宫藏', price: 2600 },
      { name: '清明上河图', dynasty: '宋', provenance: '宫藏', price: 1500 },
      { name: '照夜白图', dynasty: '唐', provenance: '民间', price: 980 },
    ],
    columns: [
      { prop: 'name', label: '画作', width: 160 },
      {
        prop: 'dynasty',
        label: '朝代',
        width: 120,
        sortable: true,
        filters: [
          { text: '宋', value: '宋' },
          { text: '元', value: '元' },
          { text: '五代', value: '五代' },
        ],
      },
      { prop: 'price', label: '估价(万)', width: 140, align: 'right', slot: 'price' },
    ],
    groupColumns: [
      {
        label: '藏品信息',
        children: [
          { prop: 'name', label: '画作', width: 150 },
          {
            prop: 'provenance',
            label: '流传',
            width: 100,
            formatter: (r) => (r.provenance === '宫藏' ? '宫藏' : '民间'),
          },
        ],
      },
      {
        label: '估值',
        children: [
          { prop: 'dynasty', label: '朝代', width: 90, sortable: true },
          { prop: 'price', label: '估价(万)', width: 130, align: 'right', resizable: true, slot: 'price' },
        ],
      },
    ],
  }),
  methods: {
    dynastySorter(a, b) {
      const order = ['唐', '五代', '宋', '元']
      return order.indexOf(String(a.dynasty)) - order.indexOf(String(b.dynasty))
    },
  },
}
</script>

# Props

Prop Description Type Default
data Row data LhTableRow[] []
columns Column configuration LhTableColumn[] []
height Table body height (setting it enables virtual scrolling; a number is px) number \| string —
maxHeight Maximum height in non-virtual mode number \| string —
rowHeight Row height for virtual scrolling (must match the actual row height) number —
stripe / border Zebra stripes / cell borders boolean false
size Size 'small' \| 'default' \| 'large' 'default'
rowKey Row key field name string —
defaultSortProp / defaultSortOrder Default sort column / direction string / LhTableSortOrder —
sorter Custom sort function (a, b) => number —
resizable Enable column resizing (still requires a column-level resizable, and the column must have a numeric width) boolean false
defaultFilteredValues Default filter state (uncontrolled; keyed by column prop) Record<string, (string \| number)[]> —
filteredValues Controlled filter state (:filtered-values.sync) Record<string, (string \| number)[]> —
sx sx shorthand layout props — —

# Events

Event Description Callback args
sortChange Emitted when the sort changes ({ prop, order })
filterChange Emitted when a column filter changes ({ prop, values })
columnResize Emitted when a column is resized ({ prop, width })
update:filteredValues The .sync event for the controlled filter state —
rowClick Emitted when a row is clicked (row, index)

# Slots

Slot Description
<column slot name> Custom cell; scope params { row, column, index, value } (the column is picked by column.slot)
empty Content for the empty state (defaults to "暂无数据")

# Accessibility

The header row is role="row" with aria-sort on sortable columns, and the body rows are role="row"; the filter panel is role="menu", and the resize handle has an aria-label plus tabindex and supports keyboard left / right adjustment.

Last Updated: 10/12/2026, 11:57:05 PM

Copyright © 2024-2026 FengMo WenXue