通用表格开发问题记录
服务端排序字段转换、拖拽后表格不刷新、金额列扩展性、插槽命中顺序——通用表格封装中的五个真实问题。
本文是「bylcloud-web 开发问题记录」系列之一。bylcloud-web 是基于 Vue 3 + Vite + Element Plus 的企业后台系统,笔记按「现象、排查、处理、下次注意」记录开发中真实遇到的问题。
记录 1:服务端排序字段不能直接用前端 prop
通用表格里 sort-change 抛出去的是后端要用的排序字段。前端列一般写成驼峰,比如 contractAmount,但后端可能要 contract_amount。如果直接把 e.prop 传给接口,接口不会报前端错误,只是排序没效果。
所以表格组件里加了 camelToUnderscore,在排序时把字段转成下划线:
emit('sort', { column: camelToUnderscore(e.prop), asc: e.order === 'ascending' })
这个改动很小,但减少了很多页面重复处理。后面再新增列表页时,只要 column 的 prop 和接口字段有对应关系,就不用每个页面单独转换。
记录 2:拖拽排序后数据顺序对了,表格没有马上刷新
表格拖拽用 SortableJS。最开始拖拽结束后直接改数组,有时页面显示顺序和实际数组不一致,尤其是 Element Plus 表格内部还保留了一些状态。
后来处理方式是:
- 先根据拖拽行 id 找到旧位置。
- 拷贝原数组,splice 出旧数据,再插入新位置。
- 先
emit('update:data', [])清空。 - 调用
tableRef.value.doLayout()。 nextTick后再把新数组 emit 回去。
这个做法有点绕,但当时能解决 UI 不刷新的问题。以后如果重构,可以再看是否能用更干净的方式处理,但不能忽略 Element Plus 表格内部状态。
记录 3:金额列放进通用表格以后,扩展性要留口子
项目里合同、费用、薪资都会显示金额,所以我在通用表格里加了 type: 'amount',统一做千分位和大写金额。用起来很方便,但后来发现它已经带了明显业务味道。
比如有的页面只想显示千分位,不想显示大写;有的页面金额单位不是元;有的页面需要红字或负数样式。这个时候如果通用表格没有配置项,就只能继续往里面加判断。
现在回头看,类似金额列这种能力可以保留,但应该允许配置:
- 是否显示大写。
- 是否显示货币符号。
- 空值显示为
0还是-。 - 负数是否特殊样式。
记录 4:插槽判断顺序很容易写乱
通用表格同时支持列插槽、默认插槽、操作列、拖拽列、表头插槽。这里有个隐患:多个 template v-if 同时命中时,显示会变得不可控。
我在调表格时遇到过某列内容没有按预期走自定义插槽,原因是它先命中了另一段默认逻辑。后面写这种组件时,我会尽量让列类型互斥,并在 column 配置里明确字段:
actions就只渲染操作列。drag就只渲染拖拽列。type只处理内置格式。- 具名插槽优先给业务页面兜底。
通用组件最难的不是把功能做进去,而是让功能之间别互相抢。
记录 5:表头配置入口位置不能影响表格交互
表头配置按钮放在表格右上角,绝对定位。这个入口看起来简单,但要注意 z-index 和宽度。如果盖住了表头排序区域,用户点排序会变成打开配置。
后来我把它控制在右上角固定区域,并且只在 props.fields.fields 存在时展示。这样没有列配置的普通表格不会多一个无意义入口。
