47-MetaGrid:16.5KB的元数据表格
列表页的万能组件——三种数据模式(server paging/store/manual)、#[fieldName]具名插槽定制列、#operations操作列、三种导出、行内编辑、复选选择。16.5KB的Vue文件是组件库里最大的通用件。这篇拆模板层的插槽路由和script层的三模式数据源。
文章目录
源码:
browise-vue/src/components/grid/MetaGrid.vue(16.5KB)
底座:vxe-grid(VXE-Table 4.7)+ el-pagination
一、模板层:vxe-grid的插槽路由
<vxe-grid :columns="gridColumns" :data="displayData" ...>
<!-- 动态列插槽:#[字段名]_default -->
<template v-for="f in slotFieldNames" :key="f" #[`${f}_default`]="scope">
<slot :name="f" v-bind="scope" />
</template>
<!-- 操作列固定插槽 -->
<template v-if="hasOperations" #operations_default="scope">
<slot name="operations" v-bind="scope" />
</template>
</vxe-grid>
插槽转发模式——vxe-grid的列渲染走字段名_default插槽——MetaGrid把父组件传来的同名插槽原样转发进去:
<!-- 使用方 -->
<MetaGrid storeName="userStore">
<template #psnSex="{ row }">
<el-tag :type="row.psnSex === '1' ? 'success' : 'info'">
{{ row.psnSex === '1' ? '男' : '女' }}
</el-tag>
</template>
<template #operations="{ row }">
<el-button @click="edit(row)">编辑</el-button>
</template>
</MetaGrid>
#[...]的动态插槽名——Vue3的v-slot简写支持模板字符串——父组件声明什么字段名的插槽,哪一列就被定制——其他列走默认渲染。定制粒度=列,不需要整个columns重写。
slotFieldNames的来源——useSlots()拿父组件传的插槽名数组——过滤出与columns字段匹配的——只转发有效的。
二、三种数据模式
const props = withDefaults(defineProps<{
storeName?: string // 模式1/2:store的名字
pageUrl?: string // 模式1:服务端分页URL
columns?: FieldMeta[] // 模式2/3:列定义
...
}>)
| 模式 | 配置 | 数据来源 | 典型场景 |
|---|---|---|---|
| server paging | pageUrl | 自己发请求翻页 | 大数据量标准列表页 |
| store绑定 | storeName | useStore(storeName).rowset | 主从联动/编辑提交 |
| manual | columns+data prop | 父组件灌数据 | 一次性展示/嵌套表格 |
模式1(server paging)的自循环:
async function loadPage() {
loading.value = true
const resp = await httpClient.request({
url: props.pageUrl, method: props.pageMethod,
data: { ...queryParams, minRow, maxRow }
})
displayData.value = resp.data.rows
displayTotal.value = resp.data.total
loading.value = false
}
onPageChange → loadPage() // 翻页自动加载
模式2(store绑定)的响应式直通:
const stores = inject(STORE_MAP_KEY, new Map())
const store = computed(() => stores.get(props.storeName))
const displayData = computed(() => store.value?.rowset.getPrimary())
// rowset的行变化(增删改)→ displayData自动重算 → 表格更新
关键差异——模式1的displayData是本地ref(自己管);模式2是computed直通store(别人管,谁改rowset谁负责)。同一组件两种数据所有权模型——props驱动哪个就走哪个。
三、gridColumns:FieldMeta到vxe列的翻译
const gridColumns = computed(() => {
const cols = (props.columns || store.value?.meta?.columns || [])
.filter(f => f.visible !== false) // meta里visible=false的列不显示
.map(f => ({
field: f.name,
title: f.label,
width: f.width || undefined,
// codeName有值 → 字典翻译formatter
formatter: f.codeName ? dictFormatter(f.codeName) : undefined,
// displayType → 编辑器类型(行内编辑时)
editRender: props.editable ? editorFor(f.displayType) : undefined,
slots: { default: `${f.name}_default` } // 插槽路由
}))
// 复选列/序号列/操作列按配置前置后置
...
})
columns的三级来源——props.columns > store.meta.columns > 空——直接传列定义(模式3)或靠元数据自动生成(describe的结果)。零代码模式下MetaGrid连columns都不传——describe元数据经store.meta到达——列从元数据自动长出来。
dictFormatter——codeName字段挂字典翻译——显示时row[f.name]的码值(“1”)翻译成名称(“男”)——字典来自useDict的缓存(第53篇dict模块的前端侧)。
四、行内编辑的editRender
function editorFor(displayType: string) {
switch (displayType) {
case 'date': return { name: '$input', props: { type: 'date' } }
case 'number': return { name: '$input', props: { type: 'number' } }
case 'datetime': return { name: '$input', props: { type: 'datetime' } }
default: return { name: '$input' }
}
}
editabled的表格开启行内编辑——双击单元格进入编辑——vxe的edit-closed事件触发——新值写回Row:
function onEditClosed({ row, column }) {
const storeRow = 找到对应的Row实例
storeRow.setItemValue(column.field, row[column.field])
// setItemValue的脏标记自动生效——collect('dirty')能收集到
}
行内编辑直通脏标记协议——表格改完collect提交——和表单编辑同一条链。
五、三种导出
function onExport(command: string) {
if (command === 'server') → window.open(exportUrl + '?token=...&' + 查询参数)
if (command === 'client') → 导出displayData(当前页数据)到Excel
if (command === 'checked') → 过滤选中的行导出
}
| 导出 | 数据范围 | 实现 |
|---|---|---|
| server | 服务端全量(按当前查询条件) | 后端ExportController(11.7KB通用导出) |
| client | 当前加载的数据 | 前端直接生成(数据已在内存) |
| checked | 勾选的行 | 复选过滤后同client |
server导出带token的坑——window.open发GET请求不能带Authorization头——token拼在query string(getAccessToken())——后端ExportController兼容query取token(与JwtAuthFilter的Cookie通道同理——第26篇双通道的第三变体)。
✅ 亮点:动态插槽名转发实现列级定制、三种数据模式的所有权差异(本地ref vs computed直通)、FieldMeta到vxe列的翻译层(含字典formatter)、行内编辑直通脏标记、三种导出的token传递方案。适合封装通用表格的人。扩展方向:第13篇describe元数据、第46篇useCenter、第24篇autoCount(total的来源)。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/yuhou25/article/details/165568453



