zoukankan      html  css  js  c++  java
  • 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来验证想法很重要 ,原理弄清楚后,后面就简单了。现在应该比半吊子进步一点点了。

  • 相关阅读:
    天梯赛5-12 愿天下有情人都是失散多年的兄妹 【dfs】
    poj2718 Smallest Difference【贪心】
    HDU problem 5635 LCP Array【思维】
    codeforces 782C Andryusha and Colored Balloons【构造】
    HDU 4278 Faulty Odometer【进制转换】
    codeforces B. The Meeting Place Cannot Be Changed【二分】
    POJ 3264 Balanced Lineup 【线段树】
    HDU 1850
    CodeForces-714C
    HDU Problem 1247 Hat's Words 【字典树】
  • 原文地址:https://www.cnblogs.com/ac1985482/p/2975805.html
Copyright © 2011-2022 走看看