公共Hooks封装之自定义表格数据列渲染useTableColumns
项目环境
Vue3.x + Ant Design Vue3.x + Vite3.x
封装思考:何为自定义表格数据列渲染,其为何种场景服务
根据实际业务场景而来,为避免法律风险,部分截图内容脱敏处理
如下图,当表格内容的列非常多时,正常情况下,我们通常采取的方式是左右两侧的列,即左侧 Key 列和右侧操作列固定,中间列内容区域滚动。而当数据列内容非常多并且每列数据都具备其真实意义时,我们该考虑采取更好的方式,对于不同的系统使用人员,通常每个人的关注点都是不一样的,因此,可以做成每个人主动去改变表格列项展示为其关注的数据列。
结合上述场景,以及优化考虑,便得到如下的个人解决方案,
useTableColumns
的封装
封装分解:主要思路 Columns
结合实际使用的 UI 框架Ant Design Vue
,Column 列描述数据对象,是 Columns 中的一项,Column 使用相同的 API.
常见的数据结构如下:
columns: [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
],
上面的数据结构中,指出了表格内每一列数据对应的表头、数据索引等相关信息,此外,还有官方文档中提供的一系列 API。结合上面已经提供的截图,思路其实很明显了,动态去变更这个 JSON 数据而已。实际使用中,将需要参与变更的数据列,添加自定义属性:addFilter
.
封装分解:下拉菜单-筛选展示数据列组件
<template #headerCell="{ column }">
<template v-if="column.key === 'action'">
<div class="flex justify-between items-center">
<span>操作</span>
<table-field-filter :columns="columns" @change="onFilterColumnChange" />
</div>
</template>
</template>
以上代码基于实际项目 UI FrameWork --
Ant Design Vue
,类似的也可以看下其他框架,如ElementUI
的Table
组件提供的相关 API 或写法.
项目内,我选择了将onFilterColumnChange
放置在了表格操作列的表头上,实际使用过程中,也可以放置在其他区域,例如筛选模块、标题等,具体还是看怎么设计,不破坏现有的布局或需要 UI 设计师稍微设计一下~
封装分解:Columns 动态变更
let includeColumns = []; // 参与过滤的列表字段集合
let excludeColumns = []; // 不参与过滤的列表字段集合
const columns = shallowRef([]); // 需要展示的列表字段集合
if (options?.initFilterKeys.length > 0) {
for (let i = 0, len = options.initFilterKeys.length; i < len; i++) {
const key = options.initFilterKeys[i];
const index = $columns.findIndex((item) => item.key === key);
$columns.splice(index, 1);
}
}
目前实现方式是将参与筛选的表格列放到一个数组内,再将不参与过滤的项放到另一个数组内,再将其合并。结合实际业务中,对于某些特殊场景可能没有对应数据,不参与显示控制,例如企业后台-企业微信/或其他类似生态账号登录的体系中,实际对于账号控制是不需要的(或因政策限制等其他原因,考虑屏蔽表格内账号显示),当然这个是结合实际业务来的,在此不做赘述~
封装分解:utils--getArrayDiff
/**
* @description 筛选两个数组不同的元素
*/
export function getArrayDiff(arr1, arr2) {
return arr1
.concat(arr2)
.filter((item, index, arr) => arr.indexOf(item) === arr.lastIndexOf(item));
}
useTableColumns.js 完整代码
import { shallowRef } from "vue";
import { cloneDeep } from "lodash-es";
import { getArrayDiff } from "@/utils/util";
export function useTableColumns(defaultColumns, options) {
if (!defaultColumns || !Array.isArray(defaultColumns)) return;
let includeColumns = []; // 参与过滤的列表字段集合
let excludeColumns = []; // 不参与过滤的列表字段集合
const columns = shallowRef([]); // 需要展示的列表字段集合
const onFilterColumnChange = (keys) => {
const orKeys = includeColumns.map((item) => item.key);
const delKeys = getArrayDiff(orKeys, keys);
const $columns = cloneDeep(includeColumns);
for (let i = 0, len = delKeys.length; i < len; i++) {
const key = delKeys[i];
const index = $columns.findIndex((item) => item.key === key);
$columns.splice(index, 1);
}
columns.value = [...$columns, ...excludeColumns];
};
// 初始化字段处理
const initColumns = () => {
const $columns = cloneDeep(defaultColumns);
if (options?.initFilterKeys.length > 0) {
for (let i = 0, len = options.initFilterKeys.length; i < len; i++) {
const key = options.initFilterKeys[i];
const index = $columns.findIndex((item) => item.key === key);
$columns.splice(index, 1);
}
}
for (let i = 0, len = $columns.length; i < len; i++) {
const item = $columns[i];
if (item.addFilter) {
includeColumns.push(item);
} else {
excludeColumns.push(item);
}
}
columns.value = $columns;
};
initColumns();
return {
columns,
onFilterColumnChange,
};
}
后续思考:当前的封装是否有问题呢?如何优化呢?
Hooks 中对于 Columns 的处理是使用 2 个数组来分别暂存需要筛选和不需要筛选的表格列,由于实际项目中暂时只有一个页面「文中截图所示」需要处理上述操作,而对于表格列数据,目前除了操作列,其他的都添加了addFilter
自定义属性,而在实际业务需求中,可能表格字段会出现以下情况:
仅简要说明
[字段A, 字段B, 字段C, 字段D, 字段E, 字段F, 字段G, 操作列 ]
如果除操作列都加上addFilter
自定义属性,则是和我目前使用的方式无异,也不存在问题,
如果以上字段中,作为标识(字段 A、字段 C、字段 G)不参与筛选,其余的字段参与筛选,目前封装的 Hooks 是不满足需求的,因为按照现有的写法会导致 colums 数组经过onFilterChange
之后,会变成
[字段A, 字段C, 字段G, 字段B, 字段E, 字段F, 操作列 ]
这种情况,对于原表格来说,原有的索引顺序被打破,仅满足了筛选,但不是原位置"删除/隐藏"的筛选,对于实际业务来说,可能不满足~
该如何解决呢?目前由于需求迭代,暂时没时间处理~待后续进行优化~
当然也更期待读者盆友们提供解决思路,或一起优化下代码吧~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南