Basic data binding with columns, pagination, and event handling.
+ + + +// Columns definition
+const basicColumns = [
+ { key: 'id', name: 'ID' },
+ { key: 'caseName', name: 'Case Name' },
+ { key: 'taskName', name: 'Task Name' },
+ { key: 'userId', name: 'User ID' },
+ { key: 'createTime', name: 'Create Time', timestamp: 'unix' },
+];
+
+ Table borders and column content alignment via border and align props.
+
// Alignment options: 'left' | 'center' | 'right'
+const styleColumns = [
+ { key: 'id', name: 'ID', align: 'center' },
+ { key: 'caseName', name: 'Case Name', align: 'left' },
+ { key: 'userId', name: 'User ID', align: 'right' },
+];
+
+ Fix columns to left or right using fixed: "left" or fixed: "right".
+
const fixedColumns = [
+ { key: 'id', name: 'ID', fixed: 'left', width: 80 },
+ { key: 'caseName', name: 'Case Name', fixed: 'left', width: 200 },
+ { key: 'taskName', name: 'Task Name' },
+ { key: 'userId', name: 'User ID' },
+ { key: 'content', name: 'Content' },
+ { key: 'createTime', name: 'Create Time', timestamp: 'unix' },
+ { key: 'actions', name: 'Actions', fixed: 'right', width: 120 },
+];
+ Built-in formatting for timestamps, dictionaries, and file sizes.
+ +const formatColumns = [
+ { key: 'id', name: 'ID' },
+ { key: 'caseName', name: 'Case Name' },
+ // timestamp: 'unix' formats Unix timestamp (seconds)
+ { key: 'createTime', name: 'Create Time', timestamp: 'unix' },
+ // filesize: true formats bytes to K/M/G
+ { key: 'fileSize', name: 'File Size', filesize: true },
+ // dict uses state.dict for lookup
+ { key: 'status', name: 'Status', dict: 'test' },
+];
+
+ Custom cell content via cellRenderer function. Returns JSX. Critical: must work correctly with the
+ mini-table probe row for dynamic height measurement.
+
import { CellRenderer, CellRendererParams } from 'element-plus';
+import { ElTag } from 'element-plus';
+
+// Custom cellRenderer returning JSX
+const statusRenderer: CellRenderer<T> = ({ cellData }) => {
+ const status = cellData as string;
+ const type = status === 'active' ? 'success' : status === 'pending' ? 'warning' : 'info';
+ return <ElTag type={type}>{status}</ElTag>;
+};
+
+const rendererColumns = [
+ { key: 'id', name: 'ID' },
+ { key: 'caseName', name: 'Case Name' },
+ { key: 'status', name: 'Status', cellRenderer: statusRenderer },
+ { key: 'actions', name: 'Actions', cellRenderer: actionRenderer },
+];
+
+ Custom header content via headerCellRenderer function. Must also sync with mini-table header probe.
+
import { HeaderCellRenderer, HeaderCellRendererParams } from 'element-plus';
+
+// Custom headerCellRenderer returning JSX
+const headerRenderer: HeaderCellRenderer<T> = ({ column }) => {
+ const col: ListTableColumn<T> = column._listTableColumn;
+ return (
+ <span>
+ <span style="color: var(--el-color-primary)">*</span> {col.title}
+ </span>
+ );
+};
+
+const headerColumns = [
+ { key: 'id', name: 'ID', headerCellRenderer },
+ { key: 'caseName', name: 'Case Name', headerCellRenderer },
+ { key: 'taskName', name: 'Task Name', headerCellRenderer },
+];
+
+ Dynamic height mode uses a hidden mini-table to probe actual row and header heights.
+ debug shows estimated values. No rowHeight or estimatedRowHeight needed —
+ it measures automatically.
+
// Dynamic height mode (no rowHeight set)
+// Mini-table probe automatically measures row height
+// ResizeObserver debounces at 50ms to prevent flicker
+
+// Fixed height mode (rowHeight set) - disables probe
+// <ListTableV2 :row-height="60" ...> // No probe needed
+
+// Manual estimate mode
+// <ListTableV2 :estimated-row-height="50" ...> // Uses this as starting estimate
+
+ Fixed height mode via :row-height="60". Disables the mini-table probe. Better performance for large
+ datasets since no measurement needed.
+
// Fixed row height - no mini-table probe needed
+// Better performance for large datasets
+<ListTableV2
+ :data="data"
+ :columns="columns"
+ :row-key="'id'"
+ :row-height="60"
+ :border="true"
+ debug
+/>
+
+ Control column widths with width (fixed) and minWidth (flexible). Columns without
+ explicit width use flexGrow: 1 to fill remaining space.
+
const widthColumns = [
+ { key: 'id', name: 'ID', width: 80 }, // Fixed 80px
+ { key: 'caseName', name: 'Case Name', minWidth: 200 }, // Min 200px, grows
+ { key: 'taskName', name: 'Task Name', minWidth: 150 }, // Min 150px, grows
+ { key: 'userId', name: 'User ID', width: 120 }, // Fixed 120px
+ // Remaining space distributed proportionally
+];
+
+ Control table dimensions with height, maxHeight, and headerHeight.
+ Auto-resizer handles width automatically.
+
// Fixed height with scrolling internally
+<ListTableV2 :height="400" ...>
+
+// Max height - table grows but caps at max
+<ListTableV2 :max-height="300" ...>
+
+// Custom header height (default is auto-probed)
+<ListTableV2 :header-height="60" ...>
+
+ Custom cell content via Vue template slots. Use slot: true on column and define
+ #columnKey template in parent.
+
// In template
+<ListTableV2 :columns="slotColumns" ...>
+ <template #status="{ row }">
+ <el-tag>{row.status}</el-tag>
+ </template>
+ <template #actions="{ row }">
+ <el-button>Edit</el-button>
+ </template>
+</ListTableV2>
+
+// In script
+const slotColumns = [
+ { key: 'id', name: 'ID', slot: true },
+ { key: 'caseName', name: 'Case Name' },
+ { key: 'status', name: 'Status', slot: true },
+ { key: 'actions', name: 'Actions', slot: true },
+];
+ Column headers support i18n via i18n key (uses vue3-i18n).
// The component uses t() from vue3-i18n internally
+// Column with i18n key:
+const i18nColumns = [
+ { key: 'id', name: 'ID' },
+ { key: 'caseName', i18n: 'table.props.0' }, // Uses t('table.props.0')
+ { key: 'taskName', i18n: 'table.props.1' },
+];
+ + All features working together: fixed columns + custom renderers + pagination + dynamic height probe + events. + This is the stress test. +
+ + + +// Combined: fixed columns + custom renderers + pagination + i18n
+const combinedColumns = [
+ { key: 'id', name: 'ID', fixed: 'left', width: 80 },
+ { key: 'caseName', i18n: 'table.props.0', fixed: 'left' },
+ { key: 'taskName', i18n: 'table.props.1' },
+ { key: 'userId', name: 'User', dict: 'test' },
+ { key: 'createTime', name: 'Time', timestamp: 'unix', minWidth: 180 },
+ { key: 'combinedStatus', name: 'Status', slot: true },
+ { key: 'combinedActions', name: 'Actions', fixed: 'right', slot: true, width: 140 },
+];
+
+ Edge case: custom cellRenderer combined with fixed columns and
+ pagination. Verifies mini-table probe handles custom renderers correctly across page changes.
+
// Edge case: cellRenderer + fixed columns + pagination
+// Must verify mini-table probe renders custom JSX correctly
+const edgeColumns = [
+ { key: 'id', fixed: 'left', cellRenderer: edgeIdRenderer },
+ { key: 'caseName', cellRenderer: edgeNameRenderer },
+ { key: 'priority', cellRenderer: edgePriorityRenderer },
+ { key: 'actions', fixed: 'right', cellRenderer: edgeActionsRenderer },
+];
+