问题记录-前端开发避坑(3)--属性迭代,分支结构

需求描述

利用过滤器,对后台数据做预处理,将不符合要求的数据替换为用户可以理解的数据,如将表示特定状态的代码替换为字符串,或将英文替换为指定中文等

鉴于Vue官方不建议继续使用内置的过滤器机制,尝试在获取到服务端数据后手动一次性过滤,再将过滤后的数据添加到表格上

思路描述

  1. 针对每个需要执行过滤的数据项,创建专门的过滤器方法,全局过滤器置于公共模块内,局部过滤器置于组件内
  2. 在组件内创建入口过滤器方法,将服务端数据作为参数传入,并在内部迭代;当执行到指定数据时,调用专门的过滤器方法
  3. 最终返回过滤完全的新数据,再执行后续操作

为了方便根据键名将数据直接匹配到表格的列,因此数据的每一行使用对象表示,一行数据为整个表格数组的一个元素

基础回顾:

JS 中获取对象键(属性名)数组的方式
  1. 通过静态方法配合 for...of 循环:
  • Object.keys(obj):返回对象自有的 可枚举字符串类型的 属性名数组;不包括继承而来的属性
  • Object.getOwnPropertyNames(obj):返回对象自有的 (包括可枚举和不可枚举)字符串类型的 属性名数组;不包括继承而来的属性
  • Object.getOwnPropertySymbols(obj):返回对象自有的 (包括可枚举和不可枚举)Symbol类型的 属性名数组;不包括继承而来的属性
  • Reflect.ownKeys(obj):返回第二和第三个方法的并集数组,即返回对象自有的 包括可枚举和不可枚举的 包括字符串类型和 Symbol 类型的 属性名集合;不包括继承而来的属性
  1. 通过 for...in 循环:返回对象的所有属性名,包括继承而来的属性

一张表解决:

JS 中获取对象属性值的方式
// 通过属性访问操作符配合属性名
let obj = { name:'小明', age:20 };
obj.name; // 或 obj['name'] ,属性名默认为字符串类型,除非显示创建了 Symbol 类型的属性名
// 通过静态方法
Object.keys(obj)
JS 中获取对象键值对的方式

Object.entries(obj):返回键值对数组,每个键值对用数组表示 [key,value]

过程中遇到问题

问题1

问题描述:迭代属性失败,没有获取到属性
问题分析:

  1. 一开始没有使用正确的迭代对象属性的方法,甚至用了数组的 foreach 方法,导致获取属性名和值失败
  2. 改进后通过 for (const key in obj ) { ... } 循环得到了属性名,但属性访问方式有误,导致新的值没有设置到正确的属性上:先是通过 obj.key 设置属性值,导致过滤后的属性值都在名为 'key' 的属性中,而不是变量 key 实际表示的如 'name'、'age' 等属性中

正确方式是通过 obj[key] 将 key 转换成其所表示的字符串属性名,然后通过这个字符串来访问和设置指定的属性

问题总结:对于属性中键和值的概念以及 JS 中获取键和值的技术理解不到位

问题2

问题描述:迭代和过滤成功,但赋值后返回的对象属性中不是预期的值
问题分析:将每一行数据过滤后的返回值对象初始化为空对象,即 let newRow = {},然后将过滤后的值赋予该对象对应的属性中,但存在问题:


如图所示,用过滤器替换性别,返回值对象的属性值仍然是原来的值,通过控制台输出发现,外面看到的值和对象实际的属性值不一样
原先以为是不同方式初始化对象导致了差异的产生,改成将原始数据的深拷贝作为 newRow 的初始化;但问题其实非常基础,是由于我在swich块内没有添加返回会终止语句,导致switch块每次都执行到最后一条defaul语句,因而前面成功赋值的过滤值又被原始值覆盖了;而由于swich语句的终止语句(break或return)在语法上并不是强制性的,因此编译通过而不会报错

问题总结:对于基本控制结构的理解不到位,编程习惯也有很大的改进空间;在代码实现阶段,需要先将基本的语法结构搭建好,之后再补充具体的数据操作和计算过程,避免被难以发现的语法错误干扰

总结

本次的错误是源于对基础概念理解不深,各个API运用不熟练,并没有太好的解决方案,只能靠多看、多写、多思考来加深理解和强化记忆

最终代码实现

// 过滤服务端原始数据表
filterServerData(serverData) {
  return serverData.map((data) => this.filterServerDataItem(data));
},
// 过滤单条(一行)服务端数据中的所有元素
filterServerDataItem(row) {
  let newRow = {};
  for (const [key, val] of Object.entries(row)) {
    newRow[key] = this.filterServerDataField(key, val);
  }
  return newRow;
},
// 过滤服务端数据中的单个数据,相当于组件所用到的所有筛选器的入口
filterServerDataField(key, val) {
  switch (key) {
    case "gender":
      return filterGender(val);
    default:
      return val;
  }
},
posted @ 2022-04-20 17:59  CJc_3103  阅读(41)  评论(0编辑  收藏  举报