@hz_yujin/vue-base-table
v1.1.17
Published
Vue 3 ProTable / ProPageTable:搜索、持久化、valueType、批量操作、骨架屏、行内编辑与移动端卡片
Maintainers
Readme
@hz_yujin/vue-base-table
本包位于 monorepo
packages/table。仓库根目录见 README。
基于 Vue 3 + TypeScript 的可复用表格组件库(VXE Table Grid),提供搜索表单与状态持久化。
- ProPageTable — 搜索 + 表格一体化(推荐)
- ProTable — 高级表格
- ProSearchForm — 可折叠搜索表单
安装
npm install @hz_yujin/vue-base-table element-plus @element-plus/icons-vue vxe-table vxe-pc-uielement-plus、vxe-table、vxe-pc-ui、@element-plus/icons-vue 为 peerDependencies,需由宿主项目安装。
注册依赖与样式
必须在入口完成依赖注册,并引入样式(缺一不可):
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import VxeUIBase from 'vxe-pc-ui'
import 'vxe-pc-ui/lib/style.css'
import VxeUITable from 'vxe-table'
import 'vxe-table/lib/style.css'
import zhCN from 'vxe-table/es/locale/lang/zh-CN'
import '@hz_yujin/vue-base-table/style.css'
// 按需引入组件
import { ProPageTable } from '@hz_yujin/vue-base-table'
// 或全局注册
import VueBaseTable from '@hz_yujin/vue-base-table'
const app = createApp(App)
app.use(ElementPlus, { locale: zhCn })
app.use(VxeUIBase)
app.use(VxeUITable)
// VxeUITable.setConfig({ i18n: (key, args) => ... }) // 可选:配置 VXE 中文
app.use(VueBaseTable) // 可选:全局注册 ProTable / ProPageTable / ProSearchForm
app.mount('#app')中文项目建议同时配置 Element Plus / VXE 的 zh-CN 语言包。
ProPageTable 用法(推荐)
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue'
import {
ProPageTable,
createSearchModel,
type ProTableColumn,
type SearchField,
} from '@hz_yujin/vue-base-table'
interface Row {
id: number
name: string
status: string
}
const searchFields: SearchField[] = [
{ key: 'keyword', label: '关键词', type: 'input', placeholder: '请输入' },
{
key: 'status',
label: '状态',
type: 'select',
options: [
{ label: '启用', value: '启用' },
{ label: '禁用', value: '禁用' },
],
},
]
const searchForm = reactive(createSearchModel(searchFields))
const columns: ProTableColumn<Row>[] = [
{ field: 'name', title: '名称', minWidth: 140, sortable: true },
{ field: 'status', title: '状态', width: 100, slot: 'status' },
{ field: 'action', title: '操作', width: 140, slot: 'action', fixed: 'right' },
]
const loading = ref(false)
const data = ref<Row[]>([])
const pagination = ref({ currentPage: 1, pageSize: 10, total: 0 })
async function loadData() {
loading.value = true
try {
// 调用业务接口,写入 data / pagination.total
} finally {
loading.value = false
}
}
function handleSearch() {
pagination.value.currentPage = 1
loadData()
}
function handlePageChange(payload: { currentPage: number; pageSize: number }) {
pagination.value.currentPage = payload.currentPage
pagination.value.pageSize = payload.pageSize
loadData()
}
onMounted(loadData)
function onSearchModelUpdate(value: Record<string, unknown>) {
// reactive 必须就地合并,勿直接 v-model 整对象替换
Object.assign(searchForm, value)
}
</script>
<template>
<ProPageTable
:search-model="searchForm"
@update:search-model="onSearchModelUpdate"
:search-fields="searchFields"
:columns="columns"
:data="data"
:loading="loading"
:pagination="pagination"
row-key="id"
selection="checkbox"
storage-key="demo-list"
@search="handleSearch"
@reset="handleSearch"
@refresh="loadData"
@page-change="handlePageChange"
>
<template #toolbar-left>
<el-button type="primary">新增</el-button>
</template>
<template #status="{ row }">
<el-tag>{{ row.status }}</el-tag>
</template>
<template #action>
<el-button link type="primary">编辑</el-button>
</template>
</ProPageTable>
</template>更完整的 API 说明见 docs/ProPageTable.md。
ProSearchForm 单独使用
<ProSearchForm
v-model="searchForm"
:fields="searchFields"
@search="handleSearch"
@reset="handleReset"
/>SearchField 支持的 type
| type | 说明 | 默认空值 |
|------|------|----------|
| input | 文本输入(默认) | '' |
| textarea | 多行文本 | '' |
| number | 数字输入 | undefined |
| select | 下拉单选 | '' |
| select-multiple | 下拉多选 | [] |
| date / date-range | 日期 / 日期范围 | '' / [] |
| datetime / datetime-range | 日期时间 / 范围 | '' / [] |
| time / time-range | 时间 / 范围 | '' / [] |
| month / year | 月份 / 年份 | '' |
| cascader | 级联选择 | [] |
| tree-select | 树形选择 | '' |
| radio / radio-button | 单选 | '' |
| checkbox / checkbox-group | 复选 | false / [] |
| switch | 开关 | false |
| autocomplete | 自动补全 | '' |
| slot | 自定义控件 | — |
未覆盖的场景可使用 type: 'slot' + #fieldKey 插槽(在 ProPageTable 上为 #search-{fieldKey})。
状态持久化
传入 storage-key 或 persist 后,自动将配置保存到 localStorage / sessionStorage:
<ProPageTable
:persist="{ storageKey: 'user-management' }"
:columns="columns"
:data="data"
:pagination="pagination"
/>| 持久化项 | 说明 |
|----------|------|
| 列显隐 / 列宽 / 列顺序 / 冻结 | VXE customConfig.storage |
| 排序字段与升降序 | 自动保存与恢复 |
| 表头筛选 | filters 勾选状态 |
| 每页条数 | pagination.pageSize |
| 搜索区展开/收起 | 折叠状态 |
| 搜索条件值 | 查询/重置时写入,刷新后恢复 |
细粒度配置:
persist={{
storageKey: 'user-list',
storage: 'local', // 或 'session'
column: true,
sort: true,
pagination: true,
searchExpanded: true,
search: true,
}}清除缓存:tableRef.value?.clearPersist()
ProTable 能力一览
| 能力 | 说明 |
|------|------|
| 序号列 | show-seq 默认开启 |
| 行选择 | selection="checkbox" / "radio",支持 reserve-selection |
| 排序 / 筛选 | 列配置 sortable、filters;支持远程;筛选可持久化 |
| valueType | digit / money / percent / date / datetime / tag / select |
| valueEnum | 枚举文案与 Tag 状态色 |
| 多级表头 | children 嵌套列 |
| 尺寸 | size="small" 等 |
| 空状态 | 默认插画 + emptyText;可用 #empty 自定义 |
| 分页 | pagination 配置 |
| 工具栏 | 刷新、列自定义、查询条件显隐;可选全屏/导出/打印 |
| 树形表格 | tree-config |
| 虚拟滚动 | virtual-scroll |
| 远程数据 | request + proxy,或 useProTableRequest 受控封装 |
| 列宽拖拽 | resizable 默认开启 |
| 移动端卡片 | mobile-card 默认开启(≤768px) |
| 插槽 | #columnSlot、#toolbar-left、#toolbar-right、#empty、#expand |
valueType / valueEnum 示例
{
field: 'status',
title: '状态',
valueType: 'tag',
valueEnum: {
启用: { text: '启用', status: 'success' },
禁用: { text: '禁用', status: 'info' },
},
}useProTableRequest(受控模式)
import { useProTableRequest } from '@hz_yujin/vue-base-table'
const {
searchModel,
searchFields,
loading,
data,
pagination,
handleSearch,
handleReset,
handlePageChange,
handleSortChange,
handleFilterChange,
refresh,
} = useProTableRequest({
columns,
searchFields: [...],
persist: { storageKey: 'user-list' },
fetcher: async ({ currentPage, pageSize, form, sort, filters }) => {
const res = await api.list({ currentPage, pageSize, ...form, sort, filters })
return { list: res.list, total: res.total }
},
})扩展能力
组件刻意做成「可注册 + 可透传 + 多插槽」结构,业务不必 fork 源码。
1. 注册自定义 valueType
import { h } from 'vue'
import { ElProgress } from 'element-plus'
import { registerValueType } from '@hz_yujin/vue-base-table'
registerValueType('progress', {
format: (v) => `${Number(v) * 100}%`,
render: ({ cellValue }) =>
h(ElProgress, { percentage: Number(cellValue) * 100, strokeWidth: 10 }),
})
// 列上使用
{ field: 'rate', title: '进度', valueType: 'progress' }2. 注册自定义搜索控件
import { registerSearchField } from '@hz_yujin/vue-base-table'
registerSearchField('my-select', MySelectComponent)
// 控件需接受 field / modelValue,并 emit update:modelValue
{ key: 'city', label: '城市', type: 'my-select' }3. 列 render / 插槽 / gridOptions / gridEvents
| 方式 | 说明 |
|------|------|
| column.render | 返回 VNode,轻量自定义单元格 |
| #{field} 插槽 | 完整自定义单元格 |
| gridOptions | 透传 VXE 全部配置 |
| gridEvents | 透传 VXE 事件 |
4. 页面区域插槽(ProPageTable)
#before / #search / #middle / #table-header / #table-footer / #after
5. 全局 / 局部默认配置
import { setProTableDefaults, provideProTableConfig } from '@hz_yujin/vue-base-table'
setProTableDefaults({ size: 'small', emptyText: 'No Data' })
// 或在布局中
provideProTableConfig({ size: 'mini' })
// 安装时一并注册
app.use(VueBaseTable, {
defaults: { size: 'small' },
valueTypes: { progress: { ... } },
searchFields: { 'my-select': MySelect },
})主题变量
可在外层覆盖:
.pro-page-table {
--pro-table-bg: #fff;
--pro-table-border: #ebeef5;
--pro-table-radius: 8px;
--pro-table-padding: 16px;
}移动端适配
默认开启:视口或容器宽度 ≤ 768px 时切换为卡片列表。
<!-- 关闭 -->
<ProPageTable :mobile-card="false" ... />
<!-- 自定义 -->
<ProPageTable
:mobile-card="{ breakpoint: 992, titleField: 'username', maxFields: 6 }"
...
/>列级:cardTitle / cardHidden / cardAction。
本地开发
npm run dev构建组件库
npm run build:lib产物:dist/index.js、dist/index.d.ts、dist/index.css。
License
MIT
