问题描述
在与后台交互的过程中遇到的关于处理数据格式的问题。
问题出现的环境背景及自己尝试过哪些方法
比如:后台传过来一个list
,格式如下
list: [
{
id: 10086,
firstName: '小',
lastName: '明',
birth: 1546072820279,
age: 11,
sex: 0,
// 其他属性
...
},
...
]
然后,我想对数据做预处理,原因有下面两点:
- 渲染在页面上之前,需要先对data中的某些项做数据处理。
- 防止后端同学修改了字段,如id -> userId,如果不统一在model层做处理,那后期维护就很麻烦,需要在页面中一个个找id,然后换成userId
我的想法是单独创建一个model.js用于统一处理这些数据预处理。
方法1: 类
// model.js
class Person{
constructor(props){
// 将原始data的所有的属性做挂载 Question1: 此处印象中应有更方便的写法用于挂载所有属性 Object.create(props)?
Object.keys(props).forEach(prop => {
this[prop] = props[prop];
});
// 将需要处理的数据进行处理/重写
this.name = props.firstName + props.lastName;
this.birthDate = new Date(props.birth);
// 假设0为男 1为女
this.sex = props.sex === 0 ? '男' : '女'
}
// 后期如需扩展,可以写一些原型方法
// 如通过id请求手机号
getPhone(){
fetch(xxx, { id: this.id }).then(...)
}
}
// 最终我们就可以直接在页面/业务组件中直接渲染format之后的list
export const formatList = list => list.map(item => new Person(item));
方法2: 代理
// model.js
const personHandler = {
get(target, property){
switch (property) {
case 'name':
return target.firstName + target.lastName;
case 'birthDate':
return new Date(target.birth);
case 'sex':
return target.sex === 0 ? '男' : '女';
// 其他属性直接返回,相比于方法1,省去了遍历挂载的过程。
// Question 2 但是这里如何给target添加原型方法呢?总不能直接target.getPhone = function(){...}吧? 那岂不是每个target都挂载了一个方法,没有必要。
default: return target[property];
}
}
};
export const formatList = list => list.map(item => new Proxy(item, personHandler));
结论
对于原因1: 我们将这些数据的预处理(与业务逻辑无关),从业务组件/逻辑中抽离出来,让业务组件/逻辑更加纯粹地处理业务。
对于原因2: 如果后端同学说将id改为userId,我只需要在class 或 proxy中加一行代码就搞定了
方法1中: this.id = props.userId
,方法2中:case 'id': return target.userId
问题: 注释中的 question1 和 2.
question3: 方法1和方法2哪个更适合处理这种场景呢。 求大佬们帮忙对比分析下。
回顾
目前在处理业务需求中这种场景的时候,会在tools.js
里增加一个对应的formatXXXData(XXX) { // 将XXX map 处理,然后return处理后的值}
的函数。 感觉这种做法不太直观,所以在考虑是否应该增加一个model.js
文件,用上面类似于 class Person
的形式来处理这些数据格式化和某些业务逻辑(比如getPhone()
)的问题。
但是这样会不会增加内存开销呢?毕竟需要将后端返回的dataList全部实例化, 设置了许多属性和方法。。
从逻辑上讲,萝卜和坑并不是一个东西,
Proxy
毕竟只是代理,如果你还有什么继承之类的需求,其实并没有那么好用。对于1你觉得的问题是在哪里?如果1没有什么问题,那就选1吧。