• jquery插件Asgrid开发小记


          最近做的一个项目中用到EasyUI,在开发起来还是非常方便的,而且文档齐全,看了两天文档,对照官方的例子,基本上都能找到相应的解决方法。但是easyUI的datagrid控件在加载数据过多的时候就会非常慢,特别是在IE上的时候,同事测试的时候500条记录从返回数据给前端到前端显示出来需要10秒左右,对于用的人来说这个等待时间太长了。是不可以接受的。有人会说为什么一定要加载这么多数据呢,可以分页嘛。其实分页每页的显示是可以选择,可以设置每页显示50或500等等。那为什么要显示500条呢,不为什么,因为需要需要显示这么多。

         好关于jquery插件开发可以看上一篇我转载过来的文章,已经非常详细了     :jQuery插件开发指南

         作为这个控件主要是为了替换easyui的datagrid控件太慢的问题。所以主要功能为一下几点:

    插件定位

    主要是为了解决加载慢的问题

    1.尽量保持easyui中datagrid控件api保持一致

    2.只做数据显示,去掉编辑功能保持轻量级

    基本格式

     (function($){
    
    })(jquery);

    如果有向我一样js是半吊子的话,可以看看

    Javascript中的自执行匿名函数

    所谓知其然而知其所以然

    插件结构

    (function ($) {
    
        //默认的参数  
        var defaults = {
        //key value的参数  
         }
    
         $.fn.AsGrid = function (options, param) {
            if (typeof options == 'string') {
                return methods[options](this, param);
            }
            var def = $.extend(defaults, options);
            return this.each(function () {
    
            });
        }
       //实现的方法 
        var methods = {
         }
    }

    首先我们定义了默认的参数 defaults ,它将在function (options, param)主入口函数的如下代码中体现出来,将传入的参数和默认参数合并,$.extend()参考  http://www.ostools.net/apidocs/apidoc?api=jquery 

     var def = $.extend(defaults, options);

    主函数中的

    if (typeof options == 'string') {
                return methods[options](this, param);
            }


    表示传入的第一个参数如果是字符串,也就是要实现的方法名,那么就执行methods里面的方法

    最后是一个返回

    return this.each(function () {
    
            });

    这样形成了一个闭包  ,不太明白的可以看javascript的闭包的形成

    为什么这里是this .each 而不是直接返回呢,这个去看看jquery对象是怎么回事。

    好这样就形成了基本的插件结构  。 

    默认参数

       //默认的参数  
        var defaults = { columns: {},
            method: "post",
            idField: "id",
            singleSelect: false,
            pageNumber: 0,
            pageSize: 10,
            rowStyler: function (index, row) { },
            data: {},
            pagination: true,
            paginationHeight: 30,
            paginationControl: null,
            headHeight: 30,
             -1,
            height: -1,
            pageNumber: 1,
            pageSize: 10,
            pageList: [10, 20, 30],
            queryParams: {},
            onLoading: function () { } //在数据加载完成后执行  
        };


          以上是默认参数设置,基本上是参考easyUI的一部分内容 。

    创建插件的Dom

      return this.each(function () {
                // 初始化  构建表格对象  
                var tb = $(this);
                var iscreate = tb.closest(".AsGridcs");
                if (iscreate.length == 0) {
                    // if (def.IsCreate) {
                    //创建是判断是否存在url 
                    if (options.url == undefined) {
                        def.url = undefined;
                    }
                    //创建表头   
                    var hd = $("<div class='AsGrid_head' style='height:" + def.headHight + "px'></div>");
                    var th = $("<div class='AsGrid_head_move'></div>");
    
                    var tr = "<table><tr>";
                    for (var i in def.columns) {
                        var col = def.columns[i];
                        if (col.checkbox) {
                            tr += "<td class='AsGrid_head_col ' style='" + col.width + "px'><input id='col_All_" + i + "' type='checkbox' /></td>";
                        }
                        else {
                            if (col.title == undefined)
                                col.title = '';
                            tr += "<td class='AsGrid_head_col' style='" + col.width + "px'>" + col.title + "</td>";
                        }
                    }
                    tr += "</tr></table>";
                    th.append(tr);
    
                    hd.append(th);
                    //创建主容器 
                    var parentdiv = $("<div class='AsGridcs' ></div>");
                    var contrentdiv = $("<div class='AsGrid_Content'></div>");
    
                    tb.before(parentdiv).appendTo(parentdiv).before(hd);
                    var grid_loading = $("<div class='AsGrid_loading'><div>正在加载,请稍后……</div></div>");
                    parentdiv.append(grid_loading);
                    var pagination = $("<div  class='AsGrid_pagination'></div>");
                    var pa_control = $("<div class='AsGrid_pagination_control'></div>");
                     
    
                    if (!def.singleSelect) {
                        CheckboxClick(tb);
                    }
                    //设置容器的区域大小
    
                    var w = 20;
                    for (var x in def.columns) {
                        var colen = def.columns[x];
                        w += colen.width;
                    }
    
                    if (def.width != undefined) {
                        parentdiv.css("width", def.width);
                        contrentdiv.css("width", def.width);
                    }
                    if (def.height != undefined) {
                        parentdiv.css("height", def.height);
                        contrentdiv.css("height", def.height - def.headHeight - def.paginationHeight - 10);
                    }
                    contrentdiv.css({ overflow: "auto" });
                    hd.css({ "overflow": "hidden",  def.width, "position": "relative" });
                    tb.addClass("AsGrid_Table");
                    tb.css("width", w);
                    th.css({ "width": 10000, "position": "relative" });
                    pagination.css("width", def.paginatinoHeight);
                    //设置容器滚动条偏移 
                    contrentdiv.scroll(function () {
                        th.css("left", -$(this).scrollLeft());
                        // th.offset({ left: -$(this).scrollLeft() });
    
                        // th.offset({ left: this.scrollLeft });
                    });
                     
                    //判断是否存储url 如果存在  直接加载  
    
                }
                if (def.url != undefined) {
                    var v = $.extend({ rows: def.pageSize, page: def.pageNumber }, def.queryParams);
                    $(".AsGrid_loading").css({ "display": "block" });
                    $.post(def.url, v, function (data) {
                        if (data.rows == undefined) {
                            tb.AsGrid("loadData", data);
                        }
                        else {
                            def.paginationControl.pagination({ total: data.total, pageNumber: def.pageNumber });
                            tb.AsGrid("loadData", data.rows);
                        }
                    }, "json");
                }
                tb.data("def", def);
            });

        首先我们获取当前对象,并查看是否有.AsGridcs的div,如果有就根据传入的值没有就开始创建dom,并设置了一些css样式

      var tb = $(this);
      var iscreate = tb.closest(".AsGridcs");
      if (iscreate.length == 0) 
      {//创建dom
      }

    当传入存在url的时候需要加载数据,这里使用了等一下要说道的 loadData来绑定数据

    if (def.url != undefined) {
                    var v = $.extend({ rows: def.pageSize, page: def.pageNumber }, def.queryParams);
                    $(".AsGrid_loading").css({ "display": "block" });
                    $.post(def.url, v, function (data) {
                        if (data.rows == undefined) {
                            tb.AsGrid("loadData", data);
                        }
                        else {
                            def.paginationControl.pagination({ total: data.total, pageNumber: def.pageNumber });
                            tb.AsGrid("loadData", data.rows);
                        }
                    }, "json");
                }
                tb.data("def", def);

    最主要的一句是最后一句 tb.data(“def”,def);

    将所有的数据保存了起来,方便后面调用

    实现方法

    这里我实现了一个loadData的方法 ,其实就是将数据转换为dom然后插入 。这里将data保存在了def.data中  

     var methods = {
            loadData: function (obj, data) {
    
                //删除所有节点 并重新加载  
                var def = obj.data("def");
                def.data = data;
                obj.children().empty();
                var a = new Array();
                var j = 0;
                var k = 0;
               //创建数据
                for (var d in data) {
                    if (k++ % 2 == 1) {
                        a[j++] = "<tr class='rowColorOdd AsGridRow'>";
                    }
                    else
                    { a[j++] = "<tr class='rowColorEve AsGridRow'>"; }
    
                    for (var i in def.columns) {
                        var col = def.columns[i];
                        if (col.checkbox) {
                            a[j++] = "<td class='AsGrid_content_ckbox' width='" + col.width + "px'><input class='col_All_" + i + "' type='checkbox' /></td>"
                        }
                        else {
                            // if (data[d][col.formatter] == undefined) {
                            var s = "";
                            if (!(data[d][col.field] == null || data[d][col.field] == undefined)) {
                                s = data[d][col.field];
                            }
                            if (col.formatter == undefined) {
                                a[j++] = "<td width='" + col.width + "px'>" + s + "</td>";
                            }
                            else {
                                a[j++] = "<td width='" + col.width + "px'>" + col.formatter(s, data[d], d) + "</td>";
                            }
                        }
                    }
                    a[j++] = "</tr>";
                }
                $(".AsGrid_loading").css({ "display": "none" });
                obj.append(a.join(''));
                a = null;
    
                //数据加载完后发生
                def.onLoading();
                 //鼠标移动事件
                mouseMove(obj)
                //初始化事件 
                obj.find("tr").click(function () {
    
                    var ev = $(this);
                    var classname = ev.attr("class");
                    var classlist = classname.split(" ");
                    var flag = false;
                    for (var o in classlist) {
                        if (classlist[o] == "selectColor") {
                            flag = true;
                            break;
                        }
                    }
                    if (flag) {
                        unselectRow(ev);
                    }
                    else {
                        //执行全部取消 
                        if (def.singleSelect) {
                            methods.unselectAll(obj);
                           }
                        selectRow(ev);
                    } 
    
                });
    
                return obj;
            }
    }


    最后我们将obj返回,这是为了支持jquery的链式操作 ,其他方法实现起来的方法都大致相同,基本就是获取数据,执行操作 ,返回值。如果方法不需要返回值可以返回自己来支持链式操作,如下根据编号选中行 

     selectRow: function (obj, index) {
                var def = obj.data("def");//获取数据
                selectRow(obj.children('tr').eq(index));//执行操作 
                return obj;//返回值 
            },

    小结

           由于项目前期写了很多代码,要是替换成别的表格控件,很多代码都不可用了,在不需要编辑只有浏览的页面实现一个尽量简洁的控件,找到定位很重要,最开始还想着要让表格支持翻页,最后使用了easyUI里的翻页控件集成了进去。然后加控制联动参数 。

          作为一个js还是个半吊子,前期做个简单的demo来验证想法很重要 ,原理弄清楚后,后面就简单了。现在应该比半吊子进步一点点了。

  • 相关阅读:
    CF1264E Beautiful League 解题报告
    CF1411G No Game No Life 解题报告
    Data structure on Bitcoin
    bitcoin Cryptography
    弹性布局Flex的基本语法
    Linq操作list
    dt某字段赋值
    List 添加数据
    dt 转 json 转实体
    队列
  • 原文地址:https://www.cnblogs.com/ac1985482/p/2975805.html
Copyright © 2020-2023  润新知