|
|
преди 2 дни | |
|---|---|---|
| .. | ||
| README.md | преди 2 дни | |
| ZmTableColumn.vue | преди 2 дни | |
| ZmTableColumnSettingTree.vue | преди 2 дни | |
| index.vue | преди 2 дни | |
| token.ts | преди 2 дни | |
| useTableComponents.ts | преди 3 месеца | |
ZmTable 是基于 Element Plus el-table / el-table-column 封装的业务表格组件,主要补了这些能力:
align 统一控制列对齐方式。| 文件 | 作用 |
|---|---|
index.vue |
表格主体,负责数据、默认样式、列配置收集、列顺序/显隐/固定渲染。 |
ZmTableColumn.vue |
列组件,负责列头按钮、排序、筛选、操作列设置入口、列宽计算。 |
ZmTableColumnSettingTree.vue |
列设置面板里的递归树,负责拖拽排序、显隐、固定按钮。 |
token.ts |
表格内部依赖注入类型和 key。 |
useTableComponents.ts |
给 TS 泛型使用的便捷导出。 |
推荐在页面里通过 useTableComponents<T>() 获取泛型组件,这样 prop、row 会更容易获得类型提示。
<script setup lang="ts">
import { useTableComponents } from '@/components/ZmTable/useTableComponents'
interface ListItem {
id: number
name: string
status: string
}
const loading = ref(false)
const list = ref<ListItem[]>([])
const { ZmTable, ZmTableColumn } = useTableComponents<ListItem>()
</script>
<template>
<ZmTable :data="list" :loading="loading">
<ZmTableColumn type="index" label="序号" :width="60" />
<ZmTableColumn prop="name" label="名称" />
<ZmTableColumn prop="status" label="状态">
<template #default="{ row }">
<el-tag>{{ row.status }}</el-tag>
</template>
</ZmTableColumn>
</ZmTable>
</template>
也可以直接用小写组件名:
<zm-table :data="list" :loading="loading">
<zm-table-column prop="name" label="名称" />
</zm-table>
ZmTable 继承大部分 Element Plus TableProps,下面是额外增加或重点关注的属性。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
data |
T[] |
必填 | 表格数据。 |
loading |
boolean |
必填 | 表格 loading 状态。 |
align |
'left' \| 'center' \| 'right' |
'center' |
全局列对齐方式。普通列会使用它;开启排序、筛选、操作列时,列头会优先左对齐。 |
columnMaxWidth |
number |
360 |
自动计算列宽时的最大宽度。 |
customClass |
boolean |
false |
为 true 时不挂载默认 .zm-table class,也就不会使用组件默认样式变量。 |
showBorder |
boolean |
false |
控制组件自己的边框显示样式。 |
showOverflowTooltip |
boolean |
true |
继承自 Element Plus。想让文字换行时传 false,再配合页面 CSS 覆盖 .cell 的换行样式。 |
组件内部默认还会给 Element Plus 表格设置这些值:
{
size: 'default',
stripe: true,
border: true,
highlightCurrentRow: true,
showOverflowTooltip: true,
scrollbarAlwaysOn: true,
tooltipOptions: {
popperClass: 'max-w-120'
}
}
ZmTableColumn 继承大部分 Element Plus TableColumnCtx,下面是额外增加或重点关注的属性。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
prop |
keyof T \| string |
- | 字段名,也会作为列设置 key 的优先来源。 |
action |
boolean |
false |
标记为操作列,并在表头显示列设置按钮。操作列本身不会进入列设置列表。 |
hideInColumnSettings |
boolean |
false |
不显示在列设置面板里,适合序号列、选择列等固定功能列。 |
isParent |
boolean |
false |
标记当前列是多级表头父级。需要控制子级列排序/显隐/固定时必须加。 |
zmSortable |
boolean |
false |
显示排序按钮。组件只维护/展示排序状态,具体排序逻辑由调用方处理。 |
zmFilterable |
boolean |
false |
显示筛选按钮和 popover。筛选内容和筛选逻辑由调用方通过 #filter 自定义。 |
sortOrder |
'asc' \| 'desc' \| null |
- | 外部受控排序状态。传了这个值之后,组件不会自己保存排序状态。 |
defaultSortOrder |
'asc' \| 'desc' \| null |
null |
非受控模式下的默认排序状态。 |
zmSortMethod |
(prop, order) => void |
- | 点击排序按钮后调用。 |
filterActive |
boolean |
- | 强制控制筛选按钮激活态。不传时根据 filterModelValue 自动判断。 |
filterModelValue |
any |
- | 筛选值,可用 v-model:filter-model-value 双向绑定。 |
realValue |
(...args) => any |
- | 获取真实展示值。自动算宽时会优先使用它;配合 coverFormatter 时也会作为 formatter。 |
coverFormatter |
boolean |
false |
为 true 时,把 realValue 作为 Element Plus 的 formatter 使用。 |
开启 zm-sortable 后,表头只显示排序按钮和排序状态图标:
i-lucide:arrow-up-downi-lucide:arrow-up-narrow-widei-lucide:arrow-down-wide-narrow点击顺序是:
null -> asc -> desc -> null
非受控用法:
<ZmTableColumn prop="meetingDate" label="会议日期" zm-sortable :zm-sort-method="handleSort" />
function handleSort(prop: string, order: 'asc' | 'desc' | null) {
query.value.sortField = prop
query.value.sortOrder = order
getList()
}
受控用法:
<ZmTableColumn
prop="meetingDate"
label="会议日期"
zm-sortable
v-model:sort-order="meetingDateOrder"
@sort-change="handleSortChange"
/>
const meetingDateOrder = ref<'asc' | 'desc' | null>(null)
function handleSortChange(payload: { prop: string; order: 'asc' | 'desc' | null }) {
query.value.sortField = payload.prop
query.value.sortOrder = payload.order
getList()
}
开启 zm-filterable 后,表头只显示筛选按钮。popover 里面展示什么、怎么过滤,都由调用方写在 #filter 插槽里。
<ZmTableColumn
prop="status"
label="状态"
zm-filterable
v-model:filter-model-value="query.status"
@filter-visible-change="handleFilterVisibleChange"
>
<template #filter="{ filterModelValue, updateFilterModelValue, close }">
<div class="p-2">
<el-select
:model-value="filterModelValue"
placeholder="请选择状态"
clearable
class="w-full"
@update:model-value="updateFilterModelValue"
>
<el-option label="启用" value="enable" />
<el-option label="停用" value="disable" />
</el-select>
<div class="mt-2 flex justify-end gap-2">
<el-button size="small" @click="updateFilterModelValue(undefined)">清空</el-button>
<el-button
size="small"
type="primary"
@click="
() => {
handleQuery()
close()
}
"
>
确定
</el-button>
</div>
</div>
</template>
</ZmTableColumn>
#filter 插槽会收到这些常用参数:
| 参数 | 说明 |
|---|---|
prop |
当前列字段名。 |
filterModelValue |
当前筛选值。 |
updateFilterModelValue(value) |
更新筛选值,会触发 update:filterModelValue。 |
close() |
关闭 popover。 |
setVisible(visible) |
手动控制 popover 显隐。 |
筛选按钮是否高亮:
filterActive 时,以 filterActive 为准。filterActive 时,组件会根据 filterModelValue 是否有值自动判断。给操作列加 action,表头会显示设置按钮。
<ZmTable :data="list" :loading="loading">
<ZmTableColumn prop="name" label="名称" />
<ZmTableColumn prop="status" label="状态" />
<ZmTableColumn label="操作" width="120" fixed="right" action>
<template #default="{ row }">
<el-button link type="primary" @click="handleEdit(row)">编辑</el-button>
</template>
</ZmTableColumn>
</ZmTable>
列设置面板支持:
列设置 key 的优先级:
columnKey -> prop -> type -> label -> column-${index}
建议动态列、同名列、没有 prop 的列都手动传 column-key,避免 key 不稳定。
<ZmTableColumn column-key="custom-action" label="自定义列">
...
</ZmTableColumn>
Element Plus 原生多级表头可以直接写:
<ZmTableColumn label="累计" is-parent>
<ZmTableColumn prop="totalGasInjection" label="注气量" />
<ZmTableColumn prop="totalWaterInjection" label="注水量" />
<ZmTableColumn prop="totalPower" label="用电量" />
</ZmTableColumn>
如果想让列设置面板识别并控制子级表头,需要给父级列加 is-parent。
子级列拖拽时只能在自己的父级分组内排序。比如 累计 下面有三个子列,这三个子列只能在 累计 里面互相调整,不能被拖到其他父级外面。
普通列对齐优先级:
列自己的 align -> ZmTable 的 align -> 默认 center
开启了下面任意能力时,表头会优先左对齐,方便标题和按钮同时展示:
actionzm-sortablezm-filterable示例:
<ZmTable :data="list" :loading="loading" align="right">
<ZmTableColumn prop="amount" label="金额" />
<ZmTableColumn prop="name" label="名称" align="left" />
<ZmTableColumn prop="date" label="日期" zm-sortable />
</ZmTable>
上面例子里:
amount 使用表格全局 right。name 使用列自己的 left。date 因为开启了排序,表头优先 left。每个有 prop 的列会根据表头和当前数据自动计算 minWidth。
计算逻辑大致是:
最终宽度不会超过 ZmTable 的 columnMaxWidth,默认是 360。
<ZmTable :data="list" :loading="loading" :column-max-width="480">
<ZmTableColumn prop="description" label="描述" />
</ZmTable>
如果展示值不是原始字段值,建议传 real-value,这样自动宽度会按真实显示值计算。
<ZmTableColumn
prop="meetingDate"
label="会议日期"
cover-formatter
:real-value="(row) => dayjs(row.meetingDate).format('YYYY-MM-DD')"
/>
ZmTable 会透传 Element Plus 表格的大部分插槽,默认插槽用于放 ZmTableColumn。
ZmTableColumn 会透传 Element Plus 列的大部分插槽:
<ZmTableColumn prop="status" label="状态">
<template #default="{ row }">
<el-tag>{{ row.status }}</el-tag>
</template>
</ZmTableColumn>
如果自定义了 #header,组件内置的排序、筛选、设置按钮不会自动渲染,需要调用方自己处理表头内容。
ZmTable 暴露了内部 Element Plus 表格实例:
<script setup lang="ts">
const tableRef = ref()
function clearSelection() {
tableRef.value?.elTableRef?.clearSelection()
}
</script>
<template>
<ZmTable ref="tableRef" :data="list" :loading="loading" />
</template>
默认样式挂在 .zm-table 上。外部可以通过 class 覆盖变量:
<ZmTable class="meeting-table" :data="list" :loading="loading" />
.meeting-table {
--zm-table-font-size: 13px;
--zm-table-header-bg: #f3f6fb;
--zm-table-cell-height: 44px;
}
| 变量 | 默认值 | 说明 |
|---|---|---|
--zm-table-font-family |
inherit |
表格字体。 |
--zm-table-font-size |
12px |
表格基础字号。 |
--zm-table-text-color |
#40546d |
普通文字颜色。 |
--zm-table-strong-text-color |
#24364d |
body 单元格文字颜色。 |
--zm-table-row-font-weight |
500 |
body 单元格字重。 |
--zm-table-bg |
var(--el-bg-color) |
表格背景。 |
--zm-table-border-color |
#e7edf4 |
表格外边框颜色。 |
--zm-table-radius |
10px |
表格圆角。 |
--zm-table-header-bg |
var(--el-fill-color-extra-light, #f7f9fc) |
表头背景。 |
--zm-table-header-text-color |
var(--el-text-color-secondary, #6b7f99) |
表头文字颜色。 |
--zm-table-header-border-color |
var(--zm-table-border-color) |
表头边框颜色。 |
--zm-table-header-cell-height |
36px |
普通表头高度。 |
--zm-table-header-group-cell-height |
42px |
多级表头父级高度。 |
--zm-table-header-font-size |
var(--zm-table-font-size) |
表头字号。 |
--zm-table-header-font-weight |
600 |
表头字重。 |
--zm-table-header-line-height |
16px |
表头行高。 |
--zm-table-header-icon-btn-size |
18px |
表头图标按钮尺寸。 |
--zm-table-header-icon-btn-color |
#8aa0b8 |
表头图标默认颜色。 |
--zm-table-header-icon-btn-radius |
4px |
表头图标按钮圆角。 |
--zm-table-header-icon-btn-hover-color |
var(--el-color-primary) |
表头图标 hover 颜色。 |
--zm-table-header-icon-btn-hover-bg |
var(--el-color-primary-light-9) |
表头图标 hover 背景。 |
--zm-table-header-icon-btn-active-color |
var(--zm-table-header-icon-btn-hover-color) |
表头图标激活颜色。 |
--zm-table-header-icon-btn-active-bg |
var(--zm-table-header-icon-btn-hover-bg) |
表头图标激活背景。 |
--zm-table-header-icon-size |
16px |
表头图标尺寸。 |
--zm-table-row-border-color |
#edf2f7 |
body 单元格边框颜色。 |
--zm-table-stripe-bg |
#fcfdff |
斑马纹背景。 |
--zm-table-hover-bg |
#f5f9ff |
行 hover 背景。 |
--zm-table-current-bg |
#eef6ff |
当前行背景。 |
--zm-table-cell-height |
38px |
body 单元格高度。 |
--zm-table-cell-padding-x |
13px |
body 单元格左右 padding。 |
--zm-table-cell-first-padding-left |
calc(var(--zm-table-cell-padding-x) + 3px) |
每行第一个单元格左 padding。 |
--zm-table-cell-last-padding-right |
var(--zm-table-cell-first-padding-left) |
每行最后一个单元格右 padding。 |
--zm-table-cell-line-height |
18px |
body 单元格行高。 |
--zm-table-empty-min-height |
148px |
空状态最小高度。 |
--zm-table-empty-bg |
var(--zm-table-bg) |
空状态背景。 |
--zm-table-empty-text-font-size |
var(--zm-table-font-size) |
空状态文字字号。 |
--zm-table-empty-text-color |
var(--el-text-color-secondary) |
空状态文字颜色。 |
--zm-table-scrollbar-size |
7px |
滚动条尺寸。 |
--zm-table-scrollbar-thumb-bg |
#b8c5d6 |
滚动条滑块颜色。 |
列设置面板 popover 使用 .zm-table-column-setting-popper,可以全局覆盖,也可以在页面样式中覆盖。
| 变量 | 默认值 | 说明 |
|---|---|---|
--zm-table-column-setting-font-size |
var(--zm-table-font-size, 12px) |
设置面板字号。 |
--zm-table-column-setting-text-color |
var(--el-text-color-regular) |
设置面板文字颜色。 |
--zm-table-column-setting-border-color |
var(--el-border-color) |
设置面板分割线颜色。 |
--zm-table-column-setting-hover-bg |
var(--el-fill-color-lighter) |
设置项 hover 背景。 |
--zm-table-column-setting-radius |
6px |
设置项圆角。 |
--zm-table-column-setting-gap |
4px |
设置项纵向间距。 |
--zm-table-column-setting-max-height |
360px |
设置面板最大高度。 |
--zm-table-column-setting-row-height |
32px |
一级设置项高度。 |
--zm-table-column-setting-child-row-height |
30px |
子级设置项高度。 |
--zm-table-column-setting-item-font-weight |
400 |
普通设置项字重。 |
--zm-table-column-setting-group-font-weight |
600 |
分组设置项字重。 |
--zm-table-column-setting-icon-btn-size |
22px |
设置项图标按钮尺寸。 |
--zm-table-column-setting-icon-size |
15px |
设置项图标尺寸。 |
--zm-table-column-setting-icon-color |
#8aa0b8 |
设置项图标默认颜色。 |
--zm-table-column-setting-icon-active-color |
var(--el-color-primary) |
设置项图标激活颜色。 |
--zm-table-column-setting-icon-active-bg |
var(--el-color-primary-light-9) |
设置项图标激活背景。 |
--zm-table-column-setting-ghost-bg |
var(--el-color-primary-light-9) |
拖拽占位背景。 |
--zm-table-column-setting-ghost-opacity |
0.55 |
拖拽占位透明度。 |
自动算宽时会创建隐藏文本节点测量文字宽度,可以用这两个变量控制测量字体:
| 变量 | 默认值 | 说明 |
|---|---|---|
--zm-table-column-width-measure-font-size |
--zm-table-font-size 或当前表格字号 |
测量文字宽度时的字号。 |
--zm-table-column-width-measure-font-family |
当前表格字体或 Noto Sans SC |
测量文字宽度时的字体。 |
默认 showOverflowTooltip 是 true,单元格会走 Element Plus 的溢出 tooltip。想关闭 tooltip 并让内容自动换行,可以这样写:
<ZmTable class="wrap-table" :data="list" :loading="loading" :show-overflow-tooltip="false">
<ZmTableColumn prop="description" label="描述" />
</ZmTable>
.wrap-table {
:deep(.el-table__body .cell) {
overflow: visible;
text-overflow: initial;
white-space: normal;
word-break: break-word;
}
}
ZmTableColumn,不要在默认插槽里混入其他会渲染成列的组件。is-parent。column-key,否则列顺序和显隐状态可能因为 key 变化而重置。data 或请求接口。#header,内置排序、筛选、设置按钮不会出现。customClass=true 会关闭默认 .zm-table 样式,相关 CSS 变量也不会自动生效。