记一次前端重构

20170607149683885648699.jpg

前段时间公司项目中的用户组管理的部分交给了西安研发中心的小伙伴们做,端午前看到他们提交的代码,我内心是崩溃的,复制了我之前的css文件到各个css文件中,没用的代码全部没有删,各种html无用代码嵌套,ts文件中一大块一大块的if-else。顶着项目快要出版本的压力,我还是选择了重构,其实与其说重构还不如说重写,除了bootstrap-table配置部分和后端接口部分代码,其他都重新写了一遍。

服务

根据Angular官方的风格指南,数据交互和处理的部分应该放到服务中,这样方便复用,首先将项目中增删改查的接口交互都单独放在服务中,然后根据用户管理部分常用的数据处理部分提炼出来,放在服务中以便多个组件使用。

HTML、CSS优化

html、css部分真的是全部重写的,已经无力吐槽了,重写后html代码行数基本上减少了一半吧、css代码估计减少了有60%以上。减少了不必要的标签和css代码,一些组件引用了公司内部的组件库,页面更加符合ux的设计。

算法优化

最头疼的就是代码中的大块大块的if-else,其实这个优化的话要仔细分析一下数据结构。因为和后端交互的数据结构是类似于这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"a": [
{
"id": "string1",
"name1": "string2",
"c": [
{
"name2": "string3",
"name3": [
"string4",
"string5"
]
},
{
"name2": "string6",
"name3": [
"string7",
"string8"
]
}
]
}
]
}

其中name1是用户组名称,c表示的是权限,name2表示不同项目名称,name3表示项目中的角色名称。

主显示界面是不同用户组名称;增加界面罗列了几个不同项目,每个项目下面有不同的角色;查询页面显示用户组在这几个项目中有哪些权限。咋一看上去数据交互还是蛮复杂的,也难怪西安的小伙伴都是大片的if-else

这里用增加和修改用户组为例,讲一下我自己的优化方法。

增加用户组

增加页面是用户勾选多选框,然后提交。所以我在增加用户组的组件中,先定义了一个与提交给后端数据结构一样的对象,并额外定义了一个记录多选框的对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
addGroup = {
"a":[
{
"id":""
"name": c,
"c":[],
}
]
};
isSelected = {
"string3": [{
'string4': false,
'string5' :false
}],
"string6": [{
'string7' : false,
'string8' : false
}]
}
}

这样记录多选框的对象可以通过双向绑定和html进行交互:

1
<input type="checkbox" [(ngModel)]="isSelect.string3[0].string4" />

用户提交时,执行一个数据处理函数,把之前定义的对象作为参数传入这个函数。数据处理时,按照后端的要求,c这个对象数组中,如果任何一个对象中name3是空,这个对象是不需要增加到c数组中的,而name3中存放和name2对应的isSelected中为true的字符串名称(这段话有点绕,可以参考上面和后端交互的数据结构来理解)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
setAddGroup(isSelect:any,addGroup:any){
let isSelectArray = Object.keys(isSelect);
for( let i = 0; i < isSelectArray.length; i++){
let group = { //把c数组拆成单个对象。
name2: "",
name3: []
};
let tc = isSelect[isSelectArray[i]][0];
let tcArray = Object.keys(project);
group.name2 = isSelectArray[i];
for (let j = 0; j < tcArray.length; j++){
if (tc[tcArray[j]]){ //选中的角色放在rolename中
group.name3.push(tcArray[j])
}
}
if (group.name3.length != 0){
addGroup.a[0].c.push(group); //name3不为空时把group加到addGroup中
}
}
}

这个函数应该还有优化空间,不过比100多行的if-else还是要好很多。

编辑用户组

编辑用户组稍微麻烦一点,先从后端取得数据(后端获取的数据结构见算法优化最开始的地方),然后根据获得的数据去改变isSelect中对应的布尔值。

我写了两个函数来处理:

  • dealData函数用来遍历c数组,并把data中的name2字符串和name3数组传递给resetIsSelectData函数。
  • resetIsSelectData函数中,isSelected用传入的name2为下标,定位到isSelected对应的name2数组,然后对这个数组用传入的name3为下标修改对应的布尔值为true。这样做相当于把isSelected对象的下标由后端获取的数据控制,存在的数据就修改isSelected中对应的布尔值。
1
2
3
4
5
6
7
8
9
10
11
12
13
dealData(){
let data = this.backEndData.a[0].c
for (let i = 0; i < this.data.length; i++){
this.resetIsSelectData(this.data[i].name2,this.data[i].name3);
}
}
resetIsSelectData(name2:string,name3:any){
for (let j = 0; j < name3.length; j++){
let roleName = this.isSelect[name2][0];
roleName[name3[j]] = true;
}
}

这几行代码又压缩了100多行代码,写完了还是蛮爽的,哈哈。

最后

这次重构其实蛮心累的,表格组件一开始用的是公司内部组件库的组件,因为刚开发完成,文档也不是很全,我摸索了两天,因为bug比较多,最后还是使用bootstrap-table来做表格,也算是一个坑吧。

写代码还是要认真一点,多想一下,不是完成功能就行,毕竟title上印的是工程师而不是码农。

tc9011 wechat
欢迎订阅我的微信公众号
坚持原创技术分享,您的支持将鼓励我继续创作!