前言
作为前端,肯定遇到过对接接口的时候键名不规范的问题,接口返回的数据命名不规范,接口接收的参数命名又不规范
js
{
cDefine1: 'value1',
cDefine2: 'value2'
xxjob: 'value3'
}
那么当我们要写逻辑的时候,就要重新去命名,如果不重新命名,以后后端改键名了,如果涉及复杂的计算逻辑,你就头大了
还有同一个字段,在不同的接口,有时候返回数字,有时候返回字符串,这个很恶心人,我就遇到过,一个ID,本来它的管理列表ID这一列是数字的,然后在其他接口联查返回来又变字符串了,如果你用的是===去匹配,就会埋下深坑!
所以我把常用的自己封装的方法提取封装成了一个工具库
今天的主角就是其中的一个工具:双向映射
BiMap
BiMap是一个双向映射工具,它接收一个多维数组,然后根据传入的数组规则,生成一个映射实例
比如我这里有一个数组,涉及到深层对象、递归
js
const data = [
{
a: 1,
b: 1,
c: {
d: 1,
e: 1,
f: [
{
g: 1,
h: 1,
},
],
},
children: [
{
a: 0,
b: 0,
c: {
d: 0,
e: 0,
f: [
{
g: 0,
h: 0,
},
],
},
k: 0,
},
{
a: 1,
b: 1,
c: {
d: 1,
e: 1,
f: [
{
g: 1,
h: 1,
},
],
},
k: 1,
},
],
k: 1,
},
];
然后我使用BiMap写一个映射
js
const map = new BiMap([
["a", "A"], // 把'a'转成'A',也可以反过来把'A'转成'a'
[
"b",
"B",
{
transformType: String, // 把键名对应的value进行处理,比如转成字符串,转成数字,转成Boolean
},
],
[
"c",
"C", // 数组嵌套数组表示c是复杂对象,里面的数据还要继续转换,c.d会变成C.D
[
[
"d",
"D",
{
transformSourceType: "object", // 转换数据的类型 object、map、array
transformType: Number,
transformInverted: true, // 是否可以反过来转换 如为true就会把原本值为'否'变成0
transform: {
0: "否",
1: "是",
},
},
],
[
"e",
"E",
{
transformType: Boolean,
},
],
[
"f",
"F",
[
[
"g",
"G",
{
transformSourceType: "map",
transformType: Number,
transformInverted: true,
transform: new Map([
[0, "zero"],
[1, "one"],
]),
},
],
[
"h",
"H",
{
transformSourceType: "array",
transformType: Number,
transformInverted: true,
transformLabelKey: "label",
transformValueKey: "value",
transform: [
{
label: "否",
value: 0,
},
{
label: "是",
value: 1,
},
],
},
],
],
],
],
],
[
"children",
"CHILDREN",
{
recursion: true,
},
],
[
"k",
"K",
new BiMap([
[0, "零"],
[1, "一"],
]), // 深层对象映射可以使用数组嵌套也可以直接使用BiMap BiMap可以处理键名转换也可以处理值的转换
],
]);
BiMapConversion
BiMapConversion是一个用来把数据转换成映射后的数据的工具 它接收两个参数,一个是待转换数据,一个是BiMap规则
js
const mapData = BiMapConversion(data, map);
转换结果
如下图所示,左侧是原始数据,右侧是双向映射后的数据
在接口处统一做出入数据管理
js
import { BiMapConversion } from 'kk-utils-library/bidirectional-mapping';
import {
$factoryCreateReqItemMap,
$factoryCreateResItemMap,
$factoryDeleteReqItemMap,
$factoryDeleteResItemMap,
$factoryDetailReqItemMap,
$factoryDetailResItemMap,
$factoryListReqItemMap,
$factoryListResItemMap,
$factoryPageReqItemMap,
$factoryPageResItemMap,
$factoryUpdateReqItemMap,
$factoryUpdateResItemMap
} from '@/constants/bi-map/factory';
// 获取工厂列表
export function getFactoryList(Service) {
return (params) =>
new Promise((resolve, reject) => {
params = BiMapConversion(params || {}, $factoryListReqItemMap); // 出参转换
Service.get('/bms/factory/list', params)
.then((res) => {
res.data = BiMapConversion(res.data || [], $factoryListResItemMap); // 数据转换
resolve(res);
})
.catch((error) => reject(error));
});
}
// 获取工厂分页
export function getFactoryPage(Service) {
return (params) =>
new Promise((resolve, reject) => {
params = BiMapConversion(params || {}, $factoryPageReqItemMap);
Service.get('/bms/factory/page', params)
.then((res) => {
if (!res.data) res.data = {};
res.data.list = BiMapConversion(
res.data.list || [],
$factoryPageResItemMap
);
resolve(res);
})
.catch((error) => reject(error));
});
}
// 获取工厂详情
export function getFactoryDetail(Service) {
return (params) =>
new Promise((resolve, reject) => {
params = BiMapConversion(params || {}, $factoryDetailReqItemMap);
Service.get(`/bms/factory/getById/${params.id}`, params)
.then((res) => {
res.data = BiMapConversion(res.data || {}, $factoryDetailResItemMap);
resolve(res);
})
.catch((error) => reject(error));
});
}
// 新建工厂
export function createFactory(Service) {
return (params) =>
new Promise((resolve, reject) => {
params = BiMapConversion(params || {}, $factoryCreateReqItemMap);
Service.post('/bms/factory/save', params)
.then((res) => {
res.data = BiMapConversion(res.data || {}, $factoryCreateResItemMap);
resolve(res);
})
.catch((error) => reject(error));
});
}
// 更新工厂
export function updateFactory(Service) {
return (params) =>
new Promise((resolve, reject) => {
params = BiMapConversion(params || {}, $factoryUpdateReqItemMap);
Service.post('/bms/factory/updateById', params)
.then((res) => {
res.data = BiMapConversion(res.data || {}, $factoryUpdateResItemMap);
resolve(res);
})
.catch((error) => reject(error));
});
}
// 删除工厂
export function deleteFactory(Service) {
return (params) =>
new Promise((resolve, reject) => {
params = BiMapConversion(params || {}, $factoryDeleteReqItemMap);
Service.delete(`/bms/factory/deleteById/${params.id}`, params)
.then((res) => {
res.data = BiMapConversion(res.data || {}, $factoryDeleteResItemMap);
resolve(res);
})
.catch((error) => reject(error));
});
}
这样,只要在constants文件夹下定义好各个接口的出参映射和数据接收映射,就可以在获取接口数据的时候拿到转换后的数据了,就不用重新去命名了,以后如果后端数据不变,键名改变,就能直接在bi-map管理的地方修改,而不用去逻辑里面修改了
其他
当然 BiMap定义的数据也能复用,比如
js
// 分页参数
export const $paginationReqItemMap = new BiMap([
['pageNum', 'pageNumber'],
['pageSize', 'pageSize']
]);
// 列表
export const $listReqItemMap = new BiMap([
['code', 'code'], // 其他编码 一样的话就相当于不转换
['userName', 'userName'], // 申请人
]);
export const $expenseApplicationListResItemMap = new BiMap([
['id', 'id'], // ID
['code', 'otherCode'], // 其他编码
])
// 分页
export const $pageReqItemMap = new BiMap([
...$expenseApplicationListReqItemMap.sourceData, // BiMap实例上有个sourceData可以拿来复用
...$paginationReqItemMap.sourceData // 分页参数复用
]);
export const $pageResItemMap =
$expenseApplicationListResItemMap; // 也可以直接用同一个实例
这样用了这个工具,每次接口发送和接收的时候,都能把我们自己的键名命名换成后端所需要的,也可以把后端的键名换成前端所需要的,这样不管后台怎么定义接口的参数key或者返回数据的对象key,都不影响我们了,我们只需要在接口出入参的地方进行映射就能解决了
结语
npm库地址:kk-utils-library
我的GitHub:GitHub