zoukankan      html  css  js  c++  java
  • 前端性能优化之管理后台列表功能操作

    背景

    之前做的一个后台管理项目,在开发的时候,由于开发时间比较紧,所以在对列表做更新和删除操作的时候,
    操作成功需要更新页面数据,当时我是直接通过再次获取接口数据进行页面的更新,其实这样是有性能问题的,
    造成了服务器不必要的浪费,而且体验非常不好,页面会出现闪屏。

    优化解决过程

    本着从每一个细节做好的原则,所以今天抽时间对这块做了个优化,不需要再次获取接口数据,而是在操作
    成功后,通过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格式

    871647-20180316220933728-493672478.png

    一级菜单返回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
    标签:性能优化,总结

  • 相关阅读:
    AcWing 157. 树形地铁系统 (hash判断树同构)打卡
    AcWing 156. 矩阵 (哈希二维转一维查询)打卡
    AcWing 144. 最长异或值路径 01字典树打卡
    AcWing 143. 最大异或对 01字典树打卡
    AcWing 142. 前缀统计 字典树打卡
    AcWing 139. 回文子串的最大长度 hash打卡
    AcWing 138. 兔子与兔子 hash打卡
    常用C库函数功能及用法
    编程实现C库函数
    C语言面试题5
  • 原文地址:https://www.cnblogs.com/twodog/p/12137343.html
Copyright © 2011-2022 走看看