首页 > 代码库 > 用于后台管理的列表数据控件:DataGrid和Select

用于后台管理的列表数据控件:DataGrid和Select

常听人说不喜欢javascript。然而我一个一直用C#做后端的人,最喜欢的编程语言就是javascript了,我接收它的优点,也接收它的缺点!

前段时间接触过easyui,用过里面的DataGrid和Combobox等控件,感觉DataGrid的确减少了一些重复的工作,但是easyui改变原有的Element,比如textbox,不能用$("#id").val()获取值了,只能用$(“#id”).textbox(‘getValue‘)来获取,不喜欢这样。国庆放假,票到3号了,今天有时间就根据使用easyui的感觉写了两个数据控件DataGrid和Select。

 

先看看最后结果和前段代码:

技术分享

HTML:

文章类型:<div class="input-control select">    <select id="type" data-url="/home/TypeList"></select></div><div class="input-control text" style="width:300px;">    <input type="text" placeholder="请输入关键字" id="keyword" />    <button class="button" onclick="search()"><span class="mif-search"></span></button></div><table id="tblist" class="table border bordered" data-url="/home/PageData">    <thead>        <tr>            <th data-field="$index"></th>            <th data-field="ID">编号</th>            <th data-field="Title">标题</th>            <th data-field="Type" data-url="/home/TypeList">类型</th>            <th data-field="Author">作者</th>            <th data-field="AddTime">添加时间</th>            <th data-field="_operator" data-formatter="operateFormatter">操作</th>        </tr>    </thead></table>

JavaScript:

    <script src="http://www.mamicode.com/~/Scripts/jquery.min.js"></script>    <script src="http://www.mamicode.com/~/js/data-widget.js"></script>    <script>        var dg = new dw.DataGrid($(‘#tblist‘));        var type = new dw.Select($("#type"));        function search() {            dg.search({ keyword: $("#keyword").val(), type: $("#type").val() });        }        function operateFormatter(value, item) {            return ‘<a href="http://www.mamicode.com/##" onclick="alert(‘ + item.ID + ‘)">修改</a>‘;        }    </script>

 

 


 

Select数据控件:

id为type的select元素上有个data-url的属性,这个表示加载数据的地址,这个地址必须返回一个拥有ID和Name属性的对象数组的json格式,如下:

[{ID: 1, Name: "类型1"}, {ID: 2, Name: "类型2"}, {ID: 3, Name: "类型3"}, {ID: 4, Name: "类型4"},…]

在实例化dw.Select对象的时候,第一个参数是select元素的jquery对象,上面用$(‘type‘)得到,第二个是可选参数,说明如下:

{    value: undefined,      // 加载过数据选中的值    onInit: undefined,     // 初始化完成后执行的函数,用加载的数据作为参数    hasDefault: true,      // 是否有默认选项    defaultName: ‘请选择‘,  // 默认选项显示名    defaultID: ‘‘          // 默认选项值}

 

DataGrid数据控件:

id为tblist的table元素可有三个自定义属性:

  • data-url : 要加载数据的后台地址;
  • data-page-size : 每页显示多少条数据,默认是10,会作为查询参数的pageSize;
  • data-page-index : 加载时显示第几页,默认是1,会作为查询参数的pageIndex(可能永远也用不到,感觉默认值1很合理......);

data-url后台地址返回的格式应该如下:

{    PageCount :  100  //总页数 --int,    PageIndex :  1    //当前页 --int,    List : [         {ID:1,  Title : ‘标题1‘  ,AddTime : "/Date(1332919782070)/" },         ......    ]                // 分页数据列表---Array}

 

在实例化dw.DataGrid对象的时候,第一个参数是table元素的jquery对象,上面用$(‘tblist‘)得到,第二个是查询参数,可选。

在thead里定义表头,每个th表示一列,th可有四个自定义属性:

  • data-field:返回数据列表的对象属性名,必须;
  • data-formatter : 该列的格式化器,用于修改这列数据的显示形式,比如性别是bool,可以显示成“男”或“女”,比如上面例子中_operator列,虽然不对应任何字段,但是可以显示自定义的内容
  • data-format : 目前用于日期格式(“/Date(1332919782070)/”)的字符串(注意是字符串类型,但是是日期格式),默认值是:“yyyy-MM-dd hh:mm” 
  • data-url : 用于从ID映射成对应的Name,比如文章列表的文章类型Type返回的是类型ID,可以提供这个url返回数据,控件自动映射成类型名称,从html大号字的两个地方可以看出,地址和Select的data-url是一样的。

DataGrid对象有个search方法,参数是查询参数,用法如上。

注:加红的“查询参数”是指同一个东西,这个参数会加上pageIndex和pageSize一起post到table的data-url地址来查询数据。我用asp.net mvc做的例子中的后台Action方法签名如下:

public ActionResult PageData(string keyword, int? type, int pageSize = 10, int pageIndex = 1)

 


 

注:Select的data-url和Type列的data-url相同,在内部是有缓存的,所以加载这部分数据的时候用的是同步ajax,从加载效果可以看出只加载了一次,缓存生效了:

技术分享

 

data-widget.js依赖jQuery;

data-widget.js源码如下:

技术分享
;/*file:        data-widget.jsauthor:      loogndate :       2016-10-1descript:    DataGrid、Select、Pager*/var dw = (function () {    var dw = {};    //根据url缓存 ,没有的话要同步获取    dw.cache = {};    dw.getCache = function (url) {        var key = url.toLowerCase();        var data =http://www.mamicode.com/ dw.cache[key];        if (data) return data;        $.ajax({            url: url,            type: ‘POST‘,            async: false,            success: function (result) {                dw.cache[key] = result;                data = result;            }        });        return data;    }    var styleArr = [];    //pager.css    styleArr.push(‘table .page a{ text-decoration:none; font-weight:normal;}‘);    styleArr.push(‘table .page span{ text-decoration:none; font-weight:normal;}‘);    styleArr.push(‘table .page a:hover{ text-decoration:none;}‘);    styleArr.push(‘table .page{padding: 15px 20px;text-align: left;color: #ccc;}‘);    styleArr.push(‘table .page a{display: inline-block;color: #428bca;display: inline-block;height: 25px;    line-height: 25px;    padding: 0 10px;border: 1px solid #ddd;    margin: 0 2px;border-radius: 4px;vertical-align: middle;}‘);    styleArr.push(‘table .page span.current{display: inline-block;height: 25px;line-height: 25px;padding: 0 10px;margin: 0 2px;color: #fff;background-color: #428bca;    border: 1px solid #428bca;border-radius: 4px;vertical-align: middle;}‘);    styleArr.push(‘table .page a:hover{text-decoration: none;border: 1px solid #428bca;}‘);    styleArr.push(‘table .page span.disabled{    display: inline-block;height: 25px;line-height: 25px;padding: 0 10px;margin: 0 2px;    color: #bfbfbf;background: #f2f2f2;border: 1px solid #bfbfbf;border-radius: 4px;vertical-align: middle;}‘);    var style = $(‘<style>‘).text(styleArr.join(‘‘));    $(‘head‘).append(style);    //dateFormat(new Date(),‘yyyy-MM-dd hh:mm:ss‘)    dw.dateFormat = function (date, format) {        var o = {            "M+": date.getMonth() + 1, //month            "d+": date.getDate(), //day            "h+": date.getHours(), //hour            "m+": date.getMinutes(), //minute            "s+": date.getSeconds(), //second            "q+": Math.floor((date.getMonth() + 3) / 3), //quarter            "S": date.getMilliseconds() //millisecond        }        if (/(y+)/.test(format)) {            format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));        }        for (var k in o) {            if (new RegExp("(" + k + ")").test(format)) {                format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));            }        }        return format;    }    //得到指定url参数    dw.getQueryString = function (name) {        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", ‘i‘);        var r = window.location.search.substr(1).match(reg);        if (r !== null)            return unescape(decodeURIComponent(r[2]));        return null;    };    //得到所有url参数对象    dw.getQueryObject = function () {        var args = {};        var query = location.search.substring(1);        var pairs = query.split("&");        for (var i = 0; i < pairs.length; i++) {            var pos = pairs[i].indexOf(‘=‘);            if (pos == -1) continue;            var name = pairs[i].substring(0, pos);            var value = http://www.mamicode.com/pairs[i].substring(pos + 1);            value = decodeURIComponent(value);            args[name.toLowerCase()] = value;        }        return args;    };    return dw;}());(function (dwName, dw) {    function Pager($wrap, pageCount, current, onPageChange) {        this.$wrap = $wrap;        this.pageCount = pageCount;        this.current = current || 1;        this.onPageChange = onPageChange || function () { };        this.bindEvent();        this.render(pageCount, current);    }    Pager.prototype.render = function (pageCount, current) {        this.pageCount = pageCount;        this.current = current;        if (pageCount <= 1) {            this.$wrap.empty();            return;        }        //上一页        var htmlArr = [];        if (current > 1) {            htmlArr.push(‘<a href="javascript:;" class="prevPage">上一页</a>‘);        } else {            htmlArr.push(‘<span class="disabled">上一页</span>‘);        }        //中间页码        if (current != 1 && current >= 4 && pageCount != 4) {            htmlArr.push(‘<a href="javascript:;" class="tcdNumber">‘ + 1 + ‘</a>‘);        }        if (current - 2 > 2 && current <= pageCount && pageCount > 5) {            htmlArr.push(‘<span>...</span>‘);        }        var start = current - 2, end = current + 2;        if ((start > 1 && current < 4) || current == 1) {            end++;        }        if (current > pageCount - 4 && current >= pageCount) {            start--;        }        for (; start <= end; start++) {            if (start <= pageCount && start >= 1) {                if (start != current) {                    htmlArr.push(‘<a href="javascript:;" class="tcdNumber">‘ + start + ‘</a>‘);                } else {                    htmlArr.push(‘<span class="current">‘ + start + ‘</span>‘);                }            }        }        if (current + 2 < pageCount - 1 && current >= 1 && pageCount > 5) {            htmlArr.push(‘<span>...</span>‘);        }        if (current != pageCount && current < pageCount - 2 && pageCount != 4) {            htmlArr.push(‘<a href="javascript:;" class="tcdNumber">‘ + pageCount + ‘</a>‘);        }        //下一页        if (current < pageCount) {            htmlArr.push(‘<a href="javascript:;" class="nextPage">下一页</a>‘);        } else {            this.$wrap.remove(‘.nextPage‘);            htmlArr.push(‘<span class="disabled">下一页</span>‘);        }        //修改表现        this.$wrap.html(htmlArr.join(‘‘));    }    Pager.prototype.bindEvent = function () {        var pager = this;        this.$wrap.on("click", "a.tcdNumber", function () {            var current = parseInt($(this).text());            pager.render(pager.pageCount, current);            if (typeof (pager.onPageChange) == "function") {                pager.onPageChange(current);            }        });        //上一页        this.$wrap.on("click", "a.prevPage", function () {            var current = parseInt(pager.$wrap.children("span.current").text());            pager.render(pager.pageCount, current - 1);            if (typeof (pager.onPageChange) == "function") {                pager.onPageChange(current);            }        });        //下一页        this.$wrap.on("click", "a.nextPage", function () {            var current = parseInt(pager.$wrap.children("span.current").text());            pager.render(pager.pageCount, current + 1);            if (typeof (pager.onPageChange) == "function") {                pager.onPageChange(current);            }        });    }    dw.Pager = Pager;}(‘Pager‘, dw));(function (dwName, dw) {    function DataGrid($table, params) {        this.name = dwName;        this.$table = $table;         //表格对象        this.url = $table.data(‘url‘);       //加载数据的url        this.pageSize = $table.data(‘page-size‘) || 10;  // 每页大小        this.pageIndex = $table.data(‘page-index‘) || 1; //当前页码        this.columns = []; //列数据        this.params = {}; //查询参数        this.pager = null;//分页控件        this.isSearch = false;        var $this = this;        $table.find(‘thead>tr>th‘).each(function () {            var $th = $(this);            var field = $th.data(‘field‘);            if (field == "$index") {                if (!$th.attr("style") || $th.attr("style").indexOf("width") < 0) {                    $th.css("width", "20px");                }            }            $this.columns.push({ field: field, formatter: $th.data(‘formatter‘), format: $th.data(‘format‘), url: $th.data(‘url‘) });        });        //分页        $table.append(‘<tfoot><tr><td colspan="‘ + this.columns.length + ‘" class="page"></td></tr></tfoot>‘);        this.load(params);    }    //加载数据    DataGrid.prototype.load = function (params) {        params = params || {};        this.params = params;        params.pageIndex = this.pageIndex;        params.pageSize = this.pageSize;        var $this = this;        $.post(this.url, params, function (data) {            $this.render(data);        });    };    DataGrid.prototype.search = function (params) {        this.pageIndex = 1;        this.isSearch = true;        this.load(params);    }    DataGrid.prototype.render = function (data) {        var $datagrid = this;        var html_arr = [];        html_arr.push(‘<tbody>‘);        for (var i = 0; i < data.List.length; i++) {            var item = data.List[i];            html_arr.push(‘<tr>‘);            for (var j = 0; j < $datagrid.columns.length; j++) {                var column = this.columns[j];                html_arr.push(‘<td>‘);                if (column.field == "$index") {                    html_arr.push(this.pageSize * (this.pageIndex - 1) + i + 1);                } else {                    var renderValue =http://www.mamicode.com/ getRenderValue(item, column);                    html_arr.push(renderValue);                }                html_arr.push(‘</td>‘);            }            html_arr.push(‘</tr>‘);        }        html_arr.push(‘</tbody>‘);        var tbody = $datagrid.$table.find(‘tbody‘);        if (tbody.length > 0) {            tbody.replaceWith(html_arr.join(‘‘));            if (this.isSearch) {                $datagrid.pager.render(data.PageCount, data.PageIndex);                this.isSearch = false;            }        } else {            $datagrid.$table.append(html_arr.join(‘‘));            //分页            this.pager = new dw.Pager($datagrid.$table.find(‘.page‘), data.PageCount, data.PageIndex, function (num) {                $datagrid.pageIndex = num;                $datagrid.load($datagrid.params);            })        }    };    function urlMapping(id, list) {        for (var i = 0; i < list.length; i++) {            var item = list[i];            if (id == item.ID) {                return item.Name;            }        }        return ‘‘;    }    function getRenderValue(item, column) {        var val = item[column.field];        if (column.formatter) {            return eval(column.formatter + ‘(val,item)‘);        }        else if (column.url) {            var list = dw.getCache(column.url);            return urlMapping(val, list);        }        else {            if (typeof (val) === "string") {                if (/Date\([\d+]+\)/.test(val)) {                    var date = eval(val.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));                    val = dw.dateFormat(date, column.format || ‘yyyy-MM-dd hh:mm‘);                    return val;                }            }            return val;        }    }    dw.DataGrid = DataGrid;}(‘DataGrid‘, dw));(function (dwName, dw) {    function Select($select, params) {        this.name = dwName;        var args = $.extend({            value: undefined,            onInit: undefined,            hasDefault: true,            defaultName: ‘请选择‘,            defaultID: ‘‘        }, params);        this.$select = $select;        var url = $select.data(‘url‘);        var list = dw.getCache(url);        fillSelect(list);        //[{ID:id,Name:name}]        function fillSelect(list) {            var htmlArr = [];            if (args.hasDefault) {                htmlArr.push(‘<option value="http://www.mamicode.com/‘ + args.defaultID + ‘">‘ + args.defaultName + ‘</option>‘);            }            for (var i = 0; i < list.length; i++) {                var item = list[i];                htmlArr.push(‘<option value="http://www.mamicode.com/‘ + item.ID + ‘">‘ + item.Name + ‘</option>‘);            }            $select.html(htmlArr.join(‘‘));            if (args.value !== undefined) {                $select.val(args.value);            }            if (args.onInit && typeof (args.onInit) === "function") {                args.onInit(list);            }        }    }    dw.Select = Select;}(‘Select‘, dw));
data-widget.js

 

用于后台管理的列表数据控件:DataGrid和Select