背景
之前做的一个后台管理项目,在开发的时候,由于开发时间比较紧,所以在对列表做更新和删除操作的时候,
操作成功需要更新页面数据,当时我是直接通过再次获取接口数据进行页面的更新,其实这样是有性能问题的,
造成了服务器不必要的浪费,而且体验非常不好,页面会出现闪屏。
优化解决过程
本着从每一个细节做好的原则,所以今天抽时间对这块做了个优化,不需要再次获取接口数据,而是在操作
成功后,通过js的splice数组方法来对数据进行修改和删除,这样对性能有了一个提升,而且用户体验也变
的非常好。
这个是一个权限菜单列表的优化,一开始我以为会很好处理,后来发现这跟其他的列表还不太一样,这是一个树形的列表,意味着层级关系比较多,
所以我开始的想法是遍历整个菜单列表数据,然后通过当前操作对象id去寻找然后来移除或更新项目,但这样感觉很麻烦,后来就去看ElementUI框架(使用的是这个框架)官方文档,
发现它提供了一个当前节点的 Node 对象,参考http://element.eleme.io/#/zh-CN/component/tree中的render-content,
那这样就好办了,我们通过node.parent.data来获取到数组对象,然后进行遍历
const parent = node.parent;
const children = parent.data.children || parent.data;
这里需要注意的事,如果操作的是一级菜单,返回的是一个json数组格式,而如果是二级菜单则返回的
是一个对象json格式
一级菜单返回json
[{
"id":"4",
"menu_name":"权限管理",
"flag":"authority",
"is_display":"y",
"parent_flag":"",
"parent_id":"0",
"order_num":"9000",
"level":"1",
"dt":"2015-06-18 13:49:32",
"is_del":"n",
"del_dt":"0000-00-00 00:00:00",
"sub":Array[2]
}]
二级菜单返回json
{
"id":"225",
"menu_name":"caidan4",
"flag":"ces_menu4",
"is_display":"n",
"parent_flag":"ces",
"parent_id":"221",
"order_num":"0",
"level":"2",
"dt":"2018-03-16 20:20:01",
"is_del":"n",
"del_dt":null,
"sub":[
]
}
这里通过instanceof来判断是否是数组,然后重新赋值
let newArr = children.sub;
if(children instanceof Array){
newArr = children;
}
这里主要用到js的splice这个方法 ,从数组中删除一个对象
newArr.splice(index, 1);
splice方法是从数组中添加/删除项目,返回被删除的项目。
第一个参数是要删除项目的索引,第二个参数表示删除的数量,如果设置为0,则不删除。
需要注意的是该方法会改变原始数组
优化前的代码:
delMenu(node,p_data){
api.authority_menu_del({
id:p_data.id
})
.then((data)=>{
// console.log(data)
var _data = util.formatJson(data);
if (_data.code == 0) {
this.$message({
message: '删除成功',
type: 'success'
});
this.load_list();
}else{
this.$message.error(_data.message);
}
})
.catch((error)=>{
this.$message.error({
message: '未知错误,请联系管理员!'
});
})
},
优化后的代码:
delMenu(node,p_data){
api.authority_menu_del({
id:p_data.id
})
.then((data)=>{
// console.log(data)
var _data = util.formatJson(data);
if (_data.code == 0) {
this.$message({
message: '删除成功',
type: 'success'
});
//直接删除该节点对象 而不是重新请求数据刷新this.load_list();
const parent = node.parent;
const children = parent.data.children || parent.data;
let newArr = children.sub;
if(children instanceof Array){
newArr = children;
}
newArr.forEach((element,index) => {
if(element.id==p_data.id){
newArr.splice(index, 1);//通过索引删除对象
}
});
}else{
this.$message.error(_data.message);
}
})
.catch((error)=>{
this.$message.error({
message: '未知错误,请联系管理员!'
});
})
},
以上是对删除操作做的优化,下面还有个对更新操作做的优化
//直接修改该节点对象 而不是重新请求数据刷新this.load_list();
const parent = this.addOrUpdateNode.parent;
const children = parent.data.children || parent.data;
// console.log(JSON.stringify(children))
let newArr = children.sub;
if(children instanceof Array){
newArr = children;
}
newArr.forEach((element,index) => {
if(element.id==this.form.id){
newArr[index].id = this.form.id;
newArr[index].menu_name = this.form.menu_name;
newArr[index].menu_flag = this.form.menu_flag;
newArr[index].is_display = this.form.is_display;
newArr[index].order_num = this.form.order_num;
newArr.splice(index,1,newArr[index]);
}
});
可以看到跟上面的代码差不多,也是通过splice来做的优化
newArr.splice(index,1,newArr[index]);
根据索引先删除一个项目,然后再向数组添加一个新的项目
关于js判断是否数组主要有三种方式 参考http://www.jb51.net/article/79939.htm
1.使用typeof
2.instanceof
3.原型链方法
这里typeof有个问题
//首先看代码
var ary = [1,23,4];
console.log(typeof ary); //输出结果是Object
这个并不能实时的检测出是否是数组,只能判断其类型,所以说typeof判断基本类型数据还是挺好的,但是不能准确测试出是否是数组
instanceof使用
var ary = [1,23,4];
console.log(ary instanceof Array)//true;
原型链方法
var ary = [1,23,4];
console.log(ary.__proto__.constructor==Array);//true
console.log(ary.constructor==Array)//true 这两段代码是一样的
但是,这个是有兼容的哦,在IE早期版本里面__proto__是没有定义的
而第2,3种方法仍然有局限性,这里有个通用的原型链方法
var ary = [1,23,4];
function isArray(o){
return Object.prototype.toString.call(o)=='[object Array]';
}
console.log(isArray(ary));
总结
虽然是一个后台管理系统,仅仅是公司内部人员使用,对性能和体验要求不是很高,但是作为一个好的开发
人员,我觉得应该要养成一个好习惯,做好每一个细节,在时间满足的前提下,把事情做的最好,这样不仅仅能
够提升自己,而且把事情做完美了,领导也会对你有所赏识,何乐而不为呢 。
作者:fozero
声明:原创文章,转载请注明出处,谢谢!http://www.cnblogs.com/fozero/p/8586137.html
标签:性能优化,总结