API数据格式转换方法学习
将数据转为行列模式,方便使用统一数据格式来循环遍历来输出所有属性,并且能根据需要转换不同的值.
例子实现是用vue来演示的
一般的实现方式
原始数据是外面是items包了一层,是数组格式,然后里面每一个数组元素都是一个对象,代表每一个item,每个item里面分别是属性和值
原始数据:
"items": [
{
"goods_name": "哈哈哈",
"goods_spec_name": "11111",
"goods_price": 100,
"goods_num": 1,
"status": 2,
},
{
"goods_name": "哈哈哈11111",
"goods_spec_name": "11111",
"goods_price": 100,
"goods_num": 1,
"status": 2,
}
]
一般的写法会根据各个值进行遍历,这样的话,
代码会很长,也不整洁
不灵活,如果要处理一些值的格式化变化,就需要修改循环里面的代码,或者数据格式万一改变了,那么也要修改循环里面的代码,很容易出错
<template v-for="item in listItems">
<li class="order-border">
<div class="list-item">
<div class="li-inline li-40">
<span>商品名:</span><span>@{{item.goods_name}}</span>
</div>
<div class="li-inline li-33">
<span>规格:</span><span>@{{item.goods_spec_name}}</span>
</div>
<div class="li-inline li-15">
<span>单价:</span><span>@{{(item.goods_price/100).toFixed(2)}}</span>
</div>
<div class="li-inline li-10">
<span>数量:</span><span>@{{item.goods_num}}</span>
</div>
</div>
<div class="li-inline li-15">
<span>订单状态:</span>
<span v-if="item.status == 0">
待支付
</span>
<span v-else-if="item.status == 1">
待发货
</span>
<span v-else-if="item.status == 2">
待发货
</span>
<span v-else-if="item.status == 3">
交易完成
</span>
</div>
</div>
</li>
</template>
更好的实现方式
用更好的方式实现去解决以上的问题
将原先的数据输出改成行列模式,每一行包含多个列,每一行代表一个原始数据对象,每一列代表一个原始数据对象的一个属性,节省了输出代码,也整洁了逻辑,每一行都代表一种类型的属性,例如第一行都是商品名称相关的,第二行都是商品状态相关的
转换是需要一个转换函数进行的,将原始数据和输出数据之间搭建一个桥梁,这样有什么修改都可以修改桥梁,避免去处理输出数据,也不用去改变原始数据(很多时候上层api数据格式是不能改变的)
转换过程可以对值进行一些单独的转换处理,很灵活
<!--html的循环遍历减少了一半的代码,而且很简单,遍历listitems获得每一个item,然后遍历item获得每一个属性和对应的值-->
<template v-for="item in listItems">
<li>
<div v-for="row in item">
<div v-for="col in row">
<span class="label">@{{ col[0] }}</span>
<span class="label-value">@{{ col[1] }}</span>
</div>
</div>
</li>
</template>
这是转换函数,转换过后的值才能被行列写法的循环遍历使用
function change_list_data(all) {
var ret = [];
var data, x, y, z, row, col, def;
var key, val, opt;
var fmt = [ //建立一个过渡格式
[ // 行
// 格式说明;[key, 标题名字, 值转换函数, 选项转换函数]
['goods_name', '商品名', null, null], // 列
['goods_spec_name', '规格', null, null],
['goods_price', '单价', fee2yuan, null], //这里有一个价格的转换函数,将分转为元的单位
['goods_num', '数量', null, null]
],
[
['status', '状态', null, null]
]
];
for (x = 0; x < all.length; ++x) {
//遍历原始数据,并且每次循环的时候创建一个data变量,保存的是原始数据的当前循环的值,即保存了一个商品对象的信息,用来获取原始数据的数据的
data = all[x];
row = []; // 创建一个行变量
for (y = 0; y < fmt.length; ++y) {
//遍历过渡格式的行
col = []; //创建一个列变量
for (z = 0; z < fmt[y].length; ++z) {
//遍历过渡格式的列
def = fmt[y][z]; //获得过渡格式的列的值,如fmt[0][0]就是['goods_name', '商品名', null, null]
key = def[0]; // 先保存key
if (typeof def[2] == 'function') { // 看看值是否需要做转换处理
val = def[2](data[key]); //执行特殊转换函数,并且传入原始数据的这个key的值然后,例如转换价格
}
else {
val = data[key];
}
if (typeof def[3] == 'function') { // 看看选项是否需要做转换处理
opt = def[3](val, data[key]);//类似做法
}
else if (def[3] === null) {
opt = {}; //因为选项不能null
}
else {
opt = def[3];
}
//将修改后的数据push到列里
col.push([def[1], val, opt]);
}
//将修改后的列数据push到行里
row.push(col);
}
//将修改后的行数据push到行里
ret.push(row);
}
return ret;
}
总的来说:
关键的关键是通过一个key来实现数据沟通,
['goods_name', '商品名', null, null]
,这里的goods_name就是一个key,因为对应到原始数据的goods_name,这样转换前后的数据之间就能够互相处理
这是转换后的数据是:
[
[ //这里是一个商品对象
[ //这里是一个商品的一行属性,每行能够显示一种模式的列属性,
[ //这里是一个商品的列属性,每一行有多列,这样可以很方便的使用0,1这样来调用数组的数据,简化了操作
0=>'商品名',
1=>'哈哈哈'
],
[
0=>'规格',
1=>'1'
]
],
[ //这里是一个商品的一行属性
[
0=>'状态',
1=>'1'
],
]
],
[ //这里是第二个商品对象
[
[
0=>'商品名',
1=>'哈哈哈111'
],
[
0=>'规格',
1=>'1111'
]
],
[
[
0=>'状态',
1=>'2'
],
]
]
]
关于灵活地对值进行处理
在过渡格式里面,每一列都有4个参数
// 格式说明;[key, 标题名字, 值转换函数, 选项转换函数]
['goods_name', '商品名', null, null], // 列
在循环的时候通过判断是否是转换函数来进行转换
if (typeof def[2] == 'function') {
val = def[2](data[key]); //这里拆开来看就是一个函数传入参数的处理,因为def[2]是一个含糊是,然后()进行传参
}
else {
val = data[key];
}
例如状态值,在api数据里面是数字,但是在输出显示的时候就要用文字
所以传入一个状态转换的函数,然后方便转换数字为文字
['status', '状态', statusT, null]
//那么就使用这个转换函数
//val = def[2](data[key]);
val = statusT(data[key]); //实际上会变成这样
//例如statusT是这样的,传入数字,返回文字
function statusT(code) {
var str;
switch (code) {
case 0:
str = '未支付';
break;
case 1:
str = '待发货';
break;
case 2:
str = '已发货';
break;
}
return str;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。