欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > 通用ID转名称组件:表格字段显示与缓存策略

通用ID转名称组件:表格字段显示与缓存策略

2025/6/23 10:53:33 来源:https://blog.csdn.net/u012399690/article/details/148725618  浏览:    关键词:通用ID转名称组件:表格字段显示与缓存策略

通用ID转名称组件:表格字段显示与缓存策略

引言 📜

在Vue项目中,我们经常需要将后端返回的ID值转换为对应的名称进行展示。本文介绍一个高效的解决方案:通用ID转名称组件及其缓存机制。

核心思路 🎯

使用Pinia存储管理不同表(如分类表、平台表)的ID到名称的映射,并实现多级缓存策略:

  1. 内存缓存 - 快速访问
  2. localStorage缓存 - 持久化存储
  3. API调用 - 最终数据源

存储设计(useTableInfoStore)📦

数据结构

interface TableInfo {[key: number]: string; // ID到名称的映射
}interface TableInfoState {[tableName: string]: TableInfo; // 不同表的数据存储
}

表名与API的映射

const tableApiMap = {category: {api: getAllDsCategoryList,responseType: 'dsCategoryList',nameField: 'categoryName'},platform: {api: getAllDsPlatformList,responseType: 'dsPlatformList',nameField: 'platformName'}
} as const;

数据获取流程

graph TDA[调用getTableInfo] --> B{内存中是否有数据?}B -->|是| C[返回内存数据]B -->|否| D{localStorage中是否有缓存?}D -->|是| E[返回缓存数据并存入内存]D -->|否| F[调用API]F --> G{API调用成功?}G -->|是| H[处理数据并存入缓存]G -->|否| I[返回空对象]H --> J[返回新数据]

核心方法实现

async getTableInfo(tableName: string) {// 1. 检查内存缓存if (this.tableInfo[tableName]?.length) return this.tableInfo[tableName];// 2. 检查localStorage缓存const cachedData = localStorage.getItem(`tableInfo:${tableName}`);if (cachedData) {this.tableInfo[tableName] = JSON.parse(cachedData);return this.tableInfo[tableName];}// 3. 调用APItry {const tableConfig = tableApiMap[tableName];const res = await tableConfig.api();if (res.code === 0) {// 转换数组为ID-名称映射const tableInfo = res.data[tableConfig.responseType].reduce((acc, item) => {acc[item.id] = item[tableConfig.nameField];return acc;}, {});// 更新缓存this.tableInfo[tableName] = tableInfo;localStorage.setItem(`tableInfo:${tableName}`, JSON.stringify(tableInfo));return tableInfo;}} catch (error) {console.error(`获取${tableName}数据失败:`, error);return {};}
}

组件设计(TableText) 🧩

组件功能

  • 支持单个ID转换
  • 支持多个ID转换(数组或逗号分隔字符串)
  • 自动处理缓存更新

组件实现

<template>{{ text }}
</template><script lang="ts" setup>
// 省略导入语句interface ITableText {table: string;id?: number;ids?: string | number[];
}const props = defineProps<{ props: ITableText }>();
const text = ref('');const updateText = async () => {const { table, id, ids } = props.props;// 获取表信息const result = await tableInfoStore.getTableInfo(table);if (ids !== undefined) {// 处理多个IDconst idArray = typeof ids === 'string' ? ids.split(',').map(i => parseInt(i.trim())) : ids;text.value = idArray.map(i => result[i] || '').filter(name => name !== '').join(',');} else if (id !== undefined) {// 处理单个IDtext.value = result[id] || '';}
};// 初始化和监听变化
onMounted(updateText);
watch(() => props, updateText, { deep: true });
</script>

使用示例 🚀

单个ID展示

<el-table-column prop="categoryId" label="分类"><template #default="scope"><TableText :props="{ table: 'category', id: scope.row.categoryId }" /></template>
</el-table-column>

image.png

多个ID展示

<el-table-column prop="platformIds" label="平台"><template #default="scope"><TableText :props="{ table: 'platform', ids: scope.row.platformIds }" /></template>
</el-table-column>

数据流转示例 🔄

单个ID场景

TableText组件 TableInfoStore 后端API localStorage 获取分类信息('category') 返回内存中的映射 读取缓存 返回缓存数据 存入内存 返回缓存数据 调用getAllDsCategoryList() 返回分类列表 转换为{id: name}映射 存入缓存 存入内存 返回新数据 alt [localStorage中有缓存] [无缓存] alt [内存中有数据] [内存中无数据] 根据ID查找名称并显示 TableText组件 TableInfoStore 后端API localStorage

多个ID场景

组件接收IDs参数
拆分IDs为数组
获取表映射数据
遍历IDs查找名称
过滤空值
用逗号连接名称
显示结果

方案优势 ✨

  1. 高性能:三级缓存策略减少API调用
  2. 通用性:通过配置支持不同表类型
  3. 易用性:组件化设计简化使用
  4. 灵活性:支持单个和多个ID转换
  5. 容错性:自动处理异常情况

这个通用ID转名称解决方案通过精心设计的缓存策略和组件化实现,显著提高了表格数据显示的效率,同时保持了代码的简洁性和可维护性。

附录 🔗

pinia完整代码

web\admin\src\stores\tableInfo.ts

import { defineStore } from 'pinia';
import { getAllDsCategoryList } from '/@/api/ds/dsCategory';
import { getAllDsPlatformList } from '/@/api/ds/dsPlatform';interface TableInfo {[key: number]: string;
}interface TableInfoState {[tableName: string]: TableInfo;
}// 通用响应类型
interface BaseApiResponse {code: number;data: any;
}// 分类响应类型
interface CategoryApiResponse extends BaseApiResponse {data: {dsCategoryList: Array<{id: number;categoryName: string;}>;};
}// 平台响应类型
interface PlatformApiResponse extends BaseApiResponse {data: {dsPlatformList: Array<{id: number;platformName: string;}>;};
}// 表名与接口的映射
const tableApiMap = {category: {api: getAllDsCategoryList,responseType: 'dsCategoryList',nameField: 'categoryName'},platform: {api: getAllDsPlatformList,responseType: 'dsPlatformList',nameField: 'platformName'}
} as const;export const useTableInfoStore = defineStore('tableInfo', {state: () => ({tableInfo: {} as TableInfoState,}),actions: {async getTableInfo(tableName: string) {let key = 'tableInfo:' + tableName;console.log('开始获取表信息:', tableName);// 初始化tableInfoif (!this.tableInfo) {this.tableInfo = {} as TableInfoState;}// 如果内存中已有数据且不为空,直接返回if (this.tableInfo[tableName] && Object.keys(this.tableInfo[tableName]).length > 0) {console.log('从内存中获取数据:', this.tableInfo[tableName]);return this.tableInfo[tableName];}// 查询localStorage缓存const cachedData = localStorage.getItem(key);if (cachedData) {const parsedData = JSON.parse(cachedData) as TableInfo;// 只有当缓存数据不为空时才使用if (Object.keys(parsedData).length > 0) {this.tableInfo[tableName] = parsedData;console.log('从localStorage获取数据:', parsedData);return parsedData;} else {// 如果缓存是空对象,删除它localStorage.removeItem(key);}}// 缓存不存在或无效,根据表名请求对应接口try {let tableInfo: TableInfo = {};const tableConfig = tableApiMap[tableName as keyof typeof tableApiMap];if (tableConfig) {console.log('开始调用API:', tableName);const res = await tableConfig.api() as unknown as BaseApiResponse;console.log('API响应:', res);if (res.code === 0 && res.data[tableConfig.responseType]) {const list = res.data[tableConfig.responseType];console.log('获取到的列表数据:', list);// 将数组转换为id-name映射tableInfo = list.reduce((acc: TableInfo, item: any) => {acc[item.id] = item[tableConfig.nameField];return acc;}, {});console.log('转换后的映射数据:', tableInfo);// 保存到内存和localStorageif (Object.keys(tableInfo).length > 0) {this.tableInfo[tableName] = tableInfo;localStorage.setItem(key, JSON.stringify(tableInfo));console.log('数据已保存到缓存');}} else {console.warn('API响应格式不正确:', res);}} else {console.warn('未找到表配置:', tableName);}return tableInfo;} catch (error) {console.error(`获取${tableName}数据失败:`, error);return {};}},},
});

组件完整实现

web\admin\src\components\TableText\index.vue

<template>{{ text }}
</template><script lang="ts" setup name="TableText">
import { ref, onMounted, watch } from 'vue';
import { useTableInfoStore } from '/@/stores/tableInfo';const tableInfoStore = useTableInfoStore();interface ITableText {table: string;id?: number;ids?: string | number[];
}const props = defineProps<{ props: ITableText }>();
const text = ref('');const updateText = async () => {const { table, id, ids } = props.props;try {console.log('获取表信息:', table, 'ID:', id, 'IDs:', ids);const result = await tableInfoStore.getTableInfo(table);console.log('获取到的结果:', result);if (ids !== undefined) {// 处理多个ID的情况const idArray = typeof ids === 'string' ? ids.split(',').map(i => parseInt(i.trim())) : ids;const names = idArray.map(i => result[i] || '').filter(name => name !== '');text.value = names.join(',');} else if (id !== undefined) {// 处理单个ID的情况text.value = result[id] || '';}console.log('设置的文本值:', text.value);} catch (error) {console.error('获取文本失败:', error);text.value = '';}
};onMounted(() => {updateText();
});watch(() => props,() => {updateText();},{ deep: true }
);
</script><style scoped></style>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词