前端队长の技术博客

  1. add 20210706

我通常在根据数据做页面显示的时候,会给数据加上很多辅助属性(比如err属性,用来标识数据错误),如果数据结构比较复杂的时候,加入辅助字段后,数据结构就变得更加繁杂,每次需要从里面找数据的时候都会遍历很多层,麻烦不说,性能也大好。

(比如说是一个表格)的每一个部位(比如说一行,然后是每一个单元格)通通加上一个状态(比如err状态),当一个部位状态改变的时候,可以精细化到每一个部位的页面显示。

如下图:

image-20210611151931689

image-20210611151946937

这样的优点是每一个部位的状态都清清楚楚,缺点是数据的结构变得很复杂。

有一种解决方案是:

定义一个全局errMap,把每个部位的错误位置记录在errMap里面,比如:

errMap: {
    1: [1,2],
    3: [1]    
}

第一行的第1列和第2列,第三行的第一列显示错误标识。

这样的话,就不需要在数据结构上加上辅助的err属性字段。

类似的其他属性字段也可以用这种方式来实现。这样的话,整个数据结构就比较简单明了。

示例:

上面的表格,我需要判断:

我之前的做法是遍历表格,使用aimUsers=[[axxx,ayyy], [azzz]] 表示第一行的目标为axxx,ayyy,第二行的目标为azzz来表示。

如何判断目标在多行出现?

// 遍历aim,构建测评目标和存在的行数组
// 比如: { ajx8k: [1,2] } 表示 ajx8k测评目标,在第二行和第三行出现了

for (let key in me.aim) {
    aimExistObj[key] = [];
    aimUsers.forEach((lineAim, i)=>{
        if(lineAim.includes(key)) {
            aimExistObj[key].push(i);
        }
    })
}

其实不需要这么判断,只需要定一个对象:

aimNum: {
    axxx: 2   
}

表示axxx出现2次,那么只需要再次遍历表格,如果key===’axxx’,则找到重复的aim位置了。

对于测评人也是一样。我之前的做法是每个单元格计算user的key,如果次数大于2,则为重复,然后把所有重复的放到一个数组里面,就像这样:

blockUserRepeatErrs.push({
    idx: lineIdx,  // 行
    key: groupItem.key, // 重复的测评人key
    name: me.ansermodmap[groupItem.key] // // 重复的测评人name
});

然后将这些信息显示到表格下面。

为了表格也可以标红显示,还有再次遍历blockUserRepeatErrs,然后把对应的表格行标红处理:

// 处理单元格重复人员
if(blockUserRepeatErrs.length) {
    blockUserRepeatErrs.forEach(item=>{

        if(item.key.startsWith('a')) {
            me.$set(me.rels_inited[item.idx], 'aimerr', true);
            me.errmsg += `第${item.idx+1}行,测评目标“${item.name}组”存在重复人;<br>`;
        } else {
            let colIdx = 0;
            for (let o of me.rels_inited[item.idx].ans) {
                if(o.key === item.key) {
                    break;
                }
                colIdx++;
            }
            me.$set(me.rels_inited[item.idx].ans[colIdx], 'err', true);
            me.errmsg += `第${item.idx+1}行,测评人“${item.name}组”存在重复人;<br>`;
        }
    });
}

。。。整个过程就特别繁琐。

解决方案是:定义一个全局的变量记录错误的位置。

找到错误也很简单,只需要记录测评目标/测评人出现的次数即可。(统计测评目标在整个表格范围出现的次数,测评人在一行里面出现的次数)

然后记录到数组:行-组-重复人列表 [{ 0-am-abc1: [“BB”] }] ,这个数组就是上面说的全局数组。然后在界面上显示出来。

image

 


add 20210706

还有一点就是,我在保存错误的时候用的是对象,这就导致每次比较对象的key的时候比较麻烦,要先获取key然后使用includes进行判断。 但是我们可以采用定义两个数组的方式,一个是key数组,一个是value数组,这种在后面处理的时候就简单多了。

比如:目标重复数组,之前我的定义是:

let aimRepeat = [
    { key: 'xxx', value: 'xxx'}
]

每次需要往里面增加的时候需要判断是否存在key。需要遍历一遍aimRepeat,把key存到数组中。太麻烦了。

新的处理方式:

let aimRepeatKeys = [];
let aimRepeatVals = [];

两者是一一对应的,key添加到aimRepeatKeys的时候,value也会添加到aimRepeatVals。

下次再增加的时候,只需要使用aimRepeatKeys即可。


除了报错信息可以用这种定义全局变量的方式外,包括输入框的显示,下拉框的显示等等,也可以用这种方式。这样的话,数据结构中就不需要加入addingediting等等辅助数据了。

image

这是我在做多目标测评——关系设置的时候,李奕教我的方法。

Daotin 2021-06-11于数元网络