zoukankan      html  css  js  c++  java
  • 自己写一个轻量的JqueryGrid组件

    接触mvc不久,突然没有了viewstate和服务端控件处处都觉得不顺手,很多在webform时不必要考虑的问题都出现在眼前,这其中分页时查询条件保持的问题又是最让我头疼的事情,权衡再三,决定用ajax局部刷新列表的方式来解决这个问题。网上基于jquery的grid组件很多,jquerygrid,jqgrid等等,分别试用了一下,功能确实非常强大,但感觉上有点重,配置项太多,用起来依然感觉束手束脚,所以想来想去,还是用最笨的办法自己做了一个组件,很简陋,唯一的好处就是灵活,容易修改和控制。

    没图没真相,先来个截图看看:

    功能:

    1. 指定url,支持post或get方式加载数据
    2. 自定义数据查询条件
    3. 列定义时可以对数据项进行简单的转换处理。如:数据源[{ "name": "张三",  "age": 12, "sex": 1 }],渲染时希望把sex的值 1 显示为 男性
    4. 支持多选
    5. 支持分页
    6. 点击行时自动选中,多选时,点击checkbox进行选中和取消选中
    7. 能够返回选中项目的值,多选时返回选中值的数组

    根据个人的习惯和对功能的分解,定义了这样一个setting:

    var list = $('#list').GridView({
                'apiUrl': '/Student/List',  // 指定数据请求的URL路径
                'apiType': 'post',  // 请求的方式
                'columns': [    // 要显示的列,title对应表头,column对应数据项的属性名称,width指定列的宽度,func指定绑定时调用的函数名称
                    { title: '姓名', column: 'Name',  160 },
                    { title: '年龄', column: 'Age' },
                    { title: '性别', column: 'Sex',  100, 'func': 'convertToSex' }
                ],
                'valueColumn': 'StudentId', // data-value 取值的属性名
                'pageSize': 20, // 每页显示的数量
                'isMultiy': false,  // 是否支持多选
                'isTreeView': false,   // 是否支持树形
                'pager': 'pager',   // 指定包含分页的divid,主要是为了能单独控制pager中的一些数据,把pager给拆出来了,后来发现似乎用处不大
                'onRowClick': function(id) { }, // 当数据行被点击时执行的回调,参数是tr中的data-value
                'convertSource': function (data) { return data.body; }, // 使用数据源之前对数据进行转换。因为我的api返回的都是{ code: 200, body: [] }这种类型,需要在这里直接返回body
                'onDataBindComplete': function() {}, // 当数据加载完成,也就是列表渲染完成后的回调。比如说提醒用户加载完成之类的
                'getSearchData': function() { return $('#form1').serialize(); },    // 获取查询参数,这个很重要,想了很多办法,最终采用了这种方案,在查询前运行这个函数,将返回值作为ajax的查询参数
                'listCssClass': 'table',    // 列表table的样式名
                'pagerCssClass': 'pager',   // 分页最外面div的样式名
                'beforeSend': function() { }    // ajax请求之前调用的函数,原本是为了提醒一下加载已开始,请稍后之类的,现在没怎么用到
            });
    

    OK,接下来就是这个扩展的具体实现了,代码很多,但思路很简单,主要就是代码的拼接。大家自己看吧!

    (function ($) {
    
        $.fn.GridView = function (settings) {
            // 系统变量
            var self = this;
            self.selected = [];
            var pageindex = 1, pageSize = 20;
    
            if (settings.pageSize && $.isNumeric(settings.pageSize) && settings.pageSize > 0) {
                pageSize = settings.pageSize;
            }
    
            var rand = Math.floor(Math.random() * 1000);
            var table = $("<table" + (settings.listCssClass ? " class='" + settings.listCssClass + "'" : "") + " id='myList" + rand + "'></table>");
    
            var colgroup = colgroup2 = "<colgroup>"
            $.each(settings.columns, function (idx, item) {
                colgroup += "<col" + item.width ? " style='" + item.width + "px;'" : "" + ">";
                colgroup2 += "<col" + item.width ? " style='" + item.width + "px;'" : "" + ">";
            });
            colgroup += "<col style='18px;'></col>";
            colgroup += "</colgroup>";
            colgroup2 += "</colgroup>";
            var table = $("<table" + (settings.listCssClass ? " class='" + settings.listCssClass + "'" : "") + " id='myList" + rand + "'></table>");
    
            var pagerHtml = '<div' + (!settings.pagerCssClass ? '' : ' class="' + settings.pagerCssClass + '"') + '>';
            //var pagerHtml = '';
            pagerHtml += '<a class="disabled" id="first' + rand + '"><i class="fa fa-fast-backward"></i></a>';
            pagerHtml += '<a class="disabled" id="prev' + rand + '"><i class="fa fa-backward"></i></a>';
            pagerHtml += '<div class="pager-index"><b>第</b><input value="1" type="text" maxlength="4" id="index' + rand + '"><b>页</b></div>';
            pagerHtml += '<a class="disabled" id="next' + rand + '"><i class="fa fa-forward"></i></a>';
            pagerHtml += '<a class="disabled" id="last' + rand + '"><i class="fa fa-fast-forward"></i></a>';
            pagerHtml += '<div class="pager-info2"> 共计 <span class="totalCount" id="total' + rand + '">0</span> 条记录,';
            pagerHtml += '每页显示 <span class="pageSize' + rand + '">' + pageSize + '</span> 条,';
            pagerHtml += '共 <span class="totalPage" id="page' + rand + '">1</span> 页,';
            pagerHtml += '用时 <span class="loadTime" id="time' + rand + '">0</span>毫秒';
            pagerHtml += "</div></div>";
            var pagerDom = $(pagerHtml);
            var firstButton, prevButton, nextButton, lastButton, currentSpan, pageSizeSpan, totalCountSpan, totalPagesSpan, loadTimeSpan;
    
            // 临时变量
            var tbody, pager, cbAll, checkboxes, isPager = false, totalPage = 1;
    
            // 创建table
            self.append(table);
    
            // 创建thead
            addChildrenToTable();
    
            // 为tbody赋值
            tbody = $("#tbody" + rand);
    
            var colCount = settings.columns.length + 2;
            tbody.html("<tr class='empty'><td colspan='" + colCount + "'>等待加载数据...</td></tr>");
    
            // 创建分页
            if (settings.pager && $("#" + settings.pager)[0]) {
                pager = $("#" + settings.pager);
                isPager = true;
                pager.append(pagerDom);
                setPagerButtonEvent();
            }
    
            // 创建渲染函数
            self.fun = new Function("data", renderFunString());
    
            // 渲染第一列
            self.setFirstCol = function (val) {
                if (settings.isMulti) {
                    return "<td class='chk'><input type='checkbox' id='cb" + val + "' value='" + val + "'></td>"
                } else {
                    return "<td class='no'>" + val + "</td>";
                }
            }
    
            // 渲染最后一列
            self.setLastCol = function () {
                return "<td></td>";
            }
    
            // 渲染中间列
            self.setCol = function (content, width, cssClass, level) {
                var html = "<td";
                html += width ? " style='" + width + "px'" : "";
                html += cssClass && cssClass != 'undefined' ? " class='" + cssClass + "'" : "";
                html += ">";
                if (settings.isTreeView) {
                    html += level ? "<span class='block' style='" + 24 * level + "px'>" + (level > 0 ? "|—" : "") + "</span>" : "";
                }
                html += content && content != "undefined" ? content : "";
                html += "</td>";
                return html;
            }
    
            // 显示指定页码的数据
            self.show = function (index, type) {
                self.selected = [];
                if (!settings.apiUrl) {
                    return;
                }
    
                if (!type || type.toLowerCase() != "post") {
                    $.get(settings.apiUrl, getAjaxData(), function (data) {
                        var source = [];
                        if (settings.convertSource && $.isFunction(settings.convertSource)) {
                            source = settings.convertSource(data);
                        } else {
                            source = data;
                        }
                        addRowsToTbody(source);
                    });
                } else {
                    $.post(settings.apiUrl, getAjaxData(), function (data) {
                        var source = [];
                        if (settings.convertSource && $.isFunction(settings.convertSource)) {
                            source = settings.convertSource(data);
                        } else {
                            source = data;
                        }
                        addRowsToTbody(source);
                    });
                }
            };
    
            // 获取选中的ID
            self.getSelectedId = function () {
                if (self.selected.length == 0) {
                    return null;
                } else {
                    return self.selected[0];
                }
            };
    
            self.getSelectedIds = function () {
                return self.selected;
            };
    
            self.clear = function () {
                self.selected = [];
                $("tr", "#myList" + rand).removeClass("selected");
                $(":checkbox", "#myList" + rand).prop("checked", false);
            };
    
            // 为table内的元素绑定事件
            tbody.on("click", "tr", function () {
                if ($(this).hasClass("empty")) return;
                $("tr", tbody).removeClass("selected").find(":checkbox").prop("checked", false);
                $(this).addClass("selected").find(":checkbox").prop("checked", true);
                $("#cbAll" + rand).prop("checked", false);
                self.selected = [$(this).data("value")];
            });
    
            // 绑定复选框点击事件
            if (settings.isMulti) {
                cbAll = $("#cbAll" + rand);
    
                cbAll.on("click", function () {
                    if (!checkboxes) checkboxes = $(":checkbox", tbody);
    
                    if ($(this).prop("checked")) {
                        self.selected = [];
    
                        $.each(checkboxes, function (idx, item) {
                            $(this).prop("checked", true);
                            self.selected.push($(this).val());
    
                            var tr = $("#tr" + $(item).val());
                            if (!tr.hasClass("selected")) tr.addClass("selected");
                        });
                    } else {
                        checkboxes.prop("checked", false);
                        $("tr", tbody).removeClass("selected");
                        self.selected = [];
                    }
                });
    
                tbody.on("click", ":checkbox", function (event) {
                    event.stopPropagation();
    
                    if ($(this).prop("checked")) {
                        $("#tr" + $(this).val()).addClass("selected");
                    } else {
                        $("#tr" + $(this).val()).removeClass("selected");
                    }
                    if (!checkboxes) {
                        checkboxes = $(":checkbox", tbody);
                    }
    
                    self.selected = [];
    
                    var unCheckedCount = 0;
    
                    $.each(checkboxes, function () {
                        if ($(this).prop("checked")) {
                            self.selected.push($(this).val());
                        } else {
                            unCheckedCount++;
                        }
                    });
    
                    if (unCheckedCount > 0) {
                        cbAll.prop("checked", false);
                    } else {
                        cbAll.prop("checked", true);
                    }
                });
            }
    
            // 返回渲染函数的程序体
            function renderFunString() {
                var funString = "var self = this; var html = ''; $.each(data, function(idx, item) { var val = ";
                funString += (settings.valueColumn ? "item." + settings.valueColumn : "idx");
                funString += "; html += '<tr id="tr' + val + '" data-value="' + val + '">'; html += self.setFirstCol(val);";
                var level = null;
                if (settings.levelColumn) {
                    level = settings.levelColumn;
                }
                $.each(settings.columns, function (idx, item) {
                    if (item.func) {
                        funString += " html += self.setCol( " + item.func + "(item), " + item.width + ", '" + item.cssClass + "'" + (level ? " , item." + level : "") + " );";
                    } else {
                        funString += " html += self.setCol( item." + item.column + ", " + item.width + ", '" + item.cssClass + "'" + (level ? " , item." + level : "") + " );";
                    }
                });
                funString += " html += self.setLastCol(); html += '</tr>'; idx++; }); return html;";
                return funString;
            }
    
            // 将数据生成html,并插入到tbody中
            function addRowsToTbody(data) {
                if (data && data.body && data.body.length > 0) {
                    var html = self.fun(data.body);
                    tbody.html(html);
    
                    if (isPager) {
                        setPagerButton(pageSize, pageindex, data.totalCount, new Date().getTime());
                    }
                } else {
                    var colCount = settings.columns.length + 2;
                    tbody.html("<tr class='empty'><td colspan='" + colCount + "'>请求的数据为空</td></tr>");
                }
            }
    
            // 创建table
            function addChildrenToTable() {
                var body = "<thead>"
                if (settings.columns) {
                    if (settings.isMulti) {
                        body += "<th class='chk'><input type='checkbox' id='cbAll" + rand + "' /></th>";
                    } else {
                        body += "<th class='no'></th>";
                    }
    
                    $.each(settings.columns, function (idx, col) {
                        body += "<th>" + col.title + "</th>";
                    });
                    body += "<th></th>";
                    body += "</thead><tbody id='tbody" + rand + "'></tbody>";
    
                    table.append($(body));
                }
            }
    
            // 绑定分页按钮的点击事件
            function setPagerButtonEvent() {
                firstButton = $("#first" + rand);
                prevButton = $("#prev" + rand);
                nextButton = $("#next" + rand);
                lastButton = $("#last" + rand);
                currentSpan = $("#index" + rand);
    
                pageSizeSpan = $("#size" + rand);;
                totalCountSpan = $("#total" + rand);;
                totalPagesSpan = $("#page" + rand);;
                loadTimeSpan = $("#time" + rand);;
    
                firstButton.on("click", function () {
                    if (!$(this).hasClass("disabled")) {
                        pageindex = 1;
                        self.show();
                    }
                });
    
                prevButton.on("click", function () {
                    if (!$(this).hasClass("disabled")) {
                        pageindex -= 1;
                        pageindex = pageindex <= 0 ? 1 : pageindex;
                        self.show();
                    }
                });
    
                nextButton.on("click", function () {
                    if (!$(this).hasClass("disabled")) {
                        pageindex += 1;
                        self.show();
                    }
                });
    
                lastButton.on("click", function () {
                    if (!$(this).hasClass("disabled")) {
                        pageindex = totalPage;
                        self.show();
                    }
                });
    
                currentSpan.on("change", function () {
                    var nc = Number($(this).val());
                    if (nc && nc <= totalPage && nc > 0) {
                        pageindex = nc;
                        self.show();
                    } else {
                        $(this).val(pageindex);
                    }
                });
            }
    
            // 配置 Pager 按钮
            function setPagerButton(size, index, total, start) {
                if (total == 0) {
                    pager.hide();
                } else {
                    pager.show();
                }
    
                // 总页数
                var pages = Math.ceil(total / size);
                pages = (pages == 0 ? 1 : pages);
                totalPage = pages;
    
                if (pages == 1) {
                    if (!firstButton.hasClass("disabled")) {
                        firstButton.addClass("disabled");
                    }
                    if (!prevButton.hasClass("disabled")) {
                        prevButton.addClass("disabled");
                    }
                    if (!nextButton.hasClass("disabled")) {
                        nextButton.addClass("disabled");
                    }
                    if (!lastButton.hasClass("disabled")) {
                        lastButton.addClass("disabled");
                    }
                } else {
                    if (index == 1) {
                        if (!firstButton.hasClass("disabled")) {
                            firstButton.addClass("disabled");
                        }
                        if (!prevButton.hasClass("disabled")) {
                            prevButton.addClass("disabled");
                        }
                    } else {
                        if (firstButton.hasClass("disabled")) {
                            firstButton.removeClass("disabled");
                        }
                        if (prevButton.hasClass("disabled")) {
                            prevButton.removeClass("disabled");
                        }
                    }
                    currentSpan.val(index);
                    if (index == pages) {
                        if (!nextButton.hasClass("disabled")) {
                            nextButton.addClass("disabled");
                        }
                        if (!lastButton.hasClass("disabled")) {
                            lastButton.addClass("disabled");
                        }
                    } else {
                        if (nextButton.hasClass("disabled")) {
                            nextButton.removeClass("disabled");
                        }
                        if (lastButton.hasClass("disabled")) {
                            lastButton.removeClass("disabled");
                        }
                    }
                }
                totalCountSpan.text(total);
                pageSizeSpan.text(this.pageSize);
                totalPagesSpan.text(pages);
                loadTimeSpan.text((new Date().getTime() - start));
            }
    
            // 获取ajax的查询参数
            function getAjaxData() {
                var param;
                if ($.isFunction(settings.getSearchData)) {
                    param = settings.getSearchData();
                }
                if (isPager) {
                    if ($.isArray(param)) {                                             // $("form").serializationArray()
                        param.push({ "name": "pageSize", "value": pageSize });
                        param.push({ "name": "pageIndex", "value": pageindex });
                    } else if ($.isPlainObject(param)) {                                 // 自定义查询对象
                        $.extend(true, param, { "pageSize": pageSize, "pageIndex": pageindex });
                    } else {                                                             // $("form").serialization()
                        param = (param ? param + "&" : "") + "pageSize=" + pageSize + "&pageIndex=" + pageindex;
                    }
                }
                return !!param ? param : {};
            }
    
            return self;
        }
    
    })(jQuery);
    
    /*
     *使用范例:
     *==========================数据格式============================
     {
      "code": 200,
      "describe": "",
      "totalCount": 3,
      "body": [
        {
          "no": 1,
          "name": "王五",
          "family": {
            "father": "王老五",
            "mother": "陈静蓉"
          }
        },
        {
          "no": 2,
          "name": "张三",
          "family": {
            "father": "张作霖",
            "mother": "李培芳"
          }
        },
        {
          "no": 3,
          "name": "李四",
          "family": {
            "father": "李宗仁",
            "mother": "江少芬"
          }
        }
      ]
     }
    
     *==========================页面调用============================
        <script src="jquery-1.10.2.js"></script>
        <script src="myGrid.js"></script>
        <script>
    	    var list = $("#list").myGrid({
    		    apiUrl: "data.json",
    		    isMulti: false,
    		    isTree: true,
    		    cols: [
    			    { col: "no",  120, title: "编号", cssClass: "chk", level: 0 },
    			    { col: "name",  120, title: "姓名", level: 0 },
    			    { col: "family.father",  120, title: "父亲", level: 1, func: "addFix" }
    		    ],
    		    valueCol: "no",
    		    pager: "pager",
    		    pageSize: 2,
    		    cssClass: "default-list-table",
    		    convertSource: function(data) {
    			    return data;
    		    }
    	    });
    
            // 这个是用来转换数据的方法
    	    function addFix(obj) {
    		    return "000" + obj;
    	    }
    	    list.show();
        </script>

    一个修改的操作:

  • 相关阅读:
    20200209 ZooKeeper 3. Zookeeper内部原理
    20200209 ZooKeeper 2. Zookeeper本地模式安装
    20200209 Zookeeper 1. Zookeeper入门
    20200206 尚硅谷Docker【归档】
    20200206 Docker 8. 本地镜像发布到阿里云
    20200206 Docker 7. Docker常用安装
    20200206 Docker 6. DockerFile解析
    20200206 Docker 5. Docker容器数据卷
    20200206 Docker 4. Docker 镜像
    Combining STDP and Reward-Modulated STDP in Deep Convolutional Spiking Neural Networks for Digit Recognition
  • 原文地址:https://www.cnblogs.com/diwu0510/p/6576453.html
Copyright © 2011-2022 走看看