优化jqgrid中动态创建的colmodel

Posted

技术标签:

【中文标题】优化jqgrid中动态创建的colmodel【英文标题】:Optimize the dynamically created colmodel in jqgrid 【发布时间】:2014-11-25 02:10:47 【问题描述】:

我正在研究动态绑定的 jqgrid。我得到了所需的输出。但是我写了一个大代码,影响了我的性能并且不可读。

我需要有人可以研究这个并简单地优化我的代码。

提前致谢。

我已经在我的工作代码中转载了here

 $.each($.parseJSON(columnsData).Table1, function () 
            // debugger;
            //Push the column name.
            colHeader.push(this.Name);

            //Check the datatype of the column.
            switch (this.Datatype) 

                case 'number':
                    if (this.DefaultValue != null && this.DefaultValue != "") 
                        //  debugger;
                        colname.push(
                            name: this.Name, index: this.Name, width: 100, align: 'left', formatter: 'number', sortable: true, editable: false, sorttype: 'int', hidden: JSON.parse(this.IsHidden), editoptions: 
                                defaultValue: this.DefaultValue
                            , editrules:  required: JSON.parse(this.IsRequired) 

                        );
                    
                    else 
                        colname.push(
                            name: this.Name, index: this.Name, width: 100, align: 'left', formatter: 'number', sortable: true, editable: false, sorttype: 'int', hidden: JSON.parse(this.IsHidden), editrules:  required: JSON.parse(this.IsRequired) 
                        );
                    
                    lastFieldName = this.Name.toString(); //Store the fieldName.
                    break;
                case 'DateTime':
                    if (this.DefaultValue != null && this.DefaultValue != "") 
                        //If datetime then enable datepicker in the filter and edit form.
                        colname.push(
                            name: this.Name, search: true, index: this.Name, width: 100, stype: "text", editable: true, hidden: JSON.parse(this.IsHidden), searchoptions: 

                                dataInit: function (el) 

                                    $(el).datepicker(
                                        dateFormat: 'm/d/yy', maxDate: 0, changeMonth: true, changeYear: true, onSelect: function (dateText, inst) 
                                            setTimeout(function () 
                                                $('#TransactionsGrid')[0].triggerToolbar();
                                            , 50);
                                        
                                    );

                                
                            , editoptions: 

                                dataInit: function (el) 

                                    $(el).datepicker(
                                        dateFormat: 'm/d/yy', maxDate: 0, changeMonth: true, changeYear: true
                                    );

                                , defaultValue: this.DefaultValue, readonly: 'readonly'
                            , editrules:  required: JSON.parse(this.IsRequired) 
                        );
                    
                    else 
                        colname.push(
                            name: this.Name, search: true, index: this.Name, width: 100, stype: "text", editable: true, hidden: JSON.parse(this.IsHidden), searchoptions: 

                                dataInit: function (el) 

                                    $(el).datepicker(
                                        dateFormat: 'm/d/yy', maxDate: 0, changeMonth: true, changeYear: true, onSelect: function (dateText, inst) 
                                            setTimeout(function () 
                                                $('#TransactionsGrid')[0].triggerToolbar();
                                            , 50);
                                        
                                    );

                                
                            , editoptions: 

                                dataInit: function (el) 

                                    $(el).datepicker(
                                        dateFormat: 'm/d/yy', maxDate: 0, changeMonth: true, changeYear: true
                                    );

                                
                            , editrules:  required: JSON.parse(this.IsRequired) 
                        );
                    
                    lastFieldName = this.Name.toString();
                    break;
                case 'dropdown':
                    if (this.DefaultValue != null && this.DefaultValue != "") 
                        //   debugger;
                        if (this.ValueType == "F") 
                            colname.push(

                                name: this.Name, index: this.Name, width: 100, edittype: "select", editable: true, hidden: JSON.parse(this.IsHidden),
                                //formatter: imageFormatter, unformat: imageUnFormat,

                                /*(Set tooltip of the gridcell)
                                cellattr: function (rowId, val, rawObject, cm, rdata) 
                                if (rawObject[cm.name + "_Title"] == "") 
                                return 'title="' + rawObject[cm.name] + '"';
                                
                                else
                                return 'title="' + val + ' (' + rawObject[cm.name + "_Title"] + ')"';
                                ,*/

                                //IF dropdown then bind the values during edit form.
                                editoptions:  value: ':Select;' + this.ValueList.slice(0, -1), defaultValue: this.DefaultValue , editrules:  required: JSON.parse(this.IsRequired) , stype: 'select'
                                            , searchoptions:  value: ':All;' + this.ValueList.slice(0, -1) , align: 'left', sortable: true

                            );
                        
                        else 
                            colname.push(

                                name: this.Name, index: this.Name, width: 100, edittype: "select", label: this.ValueId, hidden: JSON.parse(this.IsHidden),


                                //IF dropdown then bind the values during edit form.
                                editoptions:  value: ':Select;' + this.ValueList.slice(0, -1), defaultValue: this.DefaultValue , editrules:  required: JSON.parse(this.IsRequired) , stype: 'select'
                                           , searchoptions:  value: ':All;' + this.ValueList.slice(0, -1) , align: 'left', sortable: true

                            );
                        
                    
                    else 
                        if (this.ValueType == "F") 
                            colname.push(

                                name: this.Name, index: this.Name, width: 100, edittype: "select", editable: true, hidden: JSON.parse(this.IsHidden),

                                //IF dropdown then bind the values during edit form.
                                editoptions:  value: ':Select;' + this.ValueList.slice(0, -1) , editrules:  required: JSON.parse(this.IsRequired) , stype: 'select'
                                            , searchoptions:  value: ':All;' + this.ValueList.slice(0, -1) , align: 'left', sortable: true

                            );
                        
                        else 
                            colname.push(

                                name: this.Name, index: this.Name, width: 100, edittype: "select", label: this.ValueId, hidden: JSON.parse(this.IsHidden),


                                //IF dropdown then bind the values during edit form.
                                editoptions:  value: ':Select;' + this.ValueList.slice(0, -1) , editrules:  required: JSON.parse(this.IsRequired) , stype: 'select'
                                           , searchoptions:  value: ':All;' + this.ValueList.slice(0, -1) , align: 'left', sortable: true

                            );
                        
                    
                    break;
                default:
                    if (this.DefaultValue != null && this.DefaultValue != "") 
                        colname.push(
                            name: this.Name, index: this.Name, width: 100, align: 'left', sortable: true, editable: true, hidden: JSON.parse(this.IsHidden), editrules:  required: JSON.parse(this.IsRequired) 
                        );
                    
                    else 
                        colname.push(
                            name: this.Name, index: this.Name, width: 100, align: 'left', sortable: true, editable: true, hidden: JSON.parse(this.IsHidden), editrules:  required: JSON.parse(this.IsRequired) 
                        );
                    
                    break;
            


        );

jQuery("#TransactionsGrid").jqGrid(
    data: $.parseJSON(gridData).BuildTransactionsDataTable,
    datatype: "local",
    hoverrows: false,
    colNames: colHeader,
    colModel: colname,
    id: 'TransactionId',
    rowNum: 10,
    rownumbers: true,
    sortname: '_id',
    viewrecords: true,
    sortorder: 'desc',
    caption: "Transaction Details",
    height: '250px',
    gridview: true,
    ignoreCase: true

);

由于代码太大而无法查看,我做了小提琴。请调查一下

更新:

我必须在我的控制器中处理的情况以及在客户端(this.DataType)中使用相同的情况时,代码将是一个大代码。

// 代码:

case FieldStyleModel.FieldType.Date:
case FieldStyleModel.FieldType.DropDownCalendar:
case FieldStyleModel.FieldType.DateWithoutDropDown:
case FieldStyleModel.FieldType.DateWithSpin:
    drColumnDetails["Datatype"] = "date";
    break;
case FieldStyleModel.FieldType.DateTime:
case FieldStyleModel.FieldType.DateTimeWithoutDropDown:
case FieldStyleModel.FieldType.DateTimeWithSpin:
    drColumnDetails["Datatype"] = "datetime";
    break;
case FieldStyleModel.FieldType.DropDown:
case FieldStyleModel.FieldType.DropDownList:
case FieldStyleModel.FieldType.DropDownValidate:
    drColumnDetails["Datatype"] = "dropdown";
    break;
case FieldStyleModel.FieldType.URL:
    drColumnDetails["Datatype"] = "hyperlink";
    break;
case FieldStyleModel.FieldType.IntegerNonNegative:
case FieldStyleModel.FieldType.IntegerNonNegativeWithSpin:
case FieldStyleModel.FieldType.IntegerPositive:
case FieldStyleModel.FieldType.IntegerPositiveWithSpin:
    drColumnDetails["Datatype"] = "number";
    break;
case FieldStyleModel.FieldType.Integer:
case FieldStyleModel.FieldType.IntegerWithSpin:
    drColumnDetails["Datatype"] = "integer";
    break;
case FieldStyleModel.FieldType.Time:
case FieldStyleModel.FieldType.TimeWithSpin:
case FieldStyleModel.FieldType.TimeZone:
    drColumnDetails["Datatype"] = "Time";
    break;
case FieldStyleModel.FieldType.CheckBox:
    drColumnDetails["Datatype"] = "checkbox";
    break;
default:
    drColumnDetails["Datatype"] = "string";
    break;

【问题讨论】:

【参考方案1】:

常识

参数height的值可以是height: 250或字符串"auto""100%"等数字。 '250px' 的值不正确。我最喜欢height 的值是"auto"。 您应该删除 jqGrid 的未知 id 选项(请参阅代码中的 id: 'TransactionId')。 值sortname: '_id' 被怀疑。您真的在输入数据的每一项中都有_id 属性吗? 如果输入数据$.parseJSON(gridData).BuildTransactionsDataTable 仅包含应被解释为文本而不是html 片段的数据,那么我建议您使用jqGrid 的autoencode: true 选项,

如果您在网格中加载数千行数据,那么the answer 中描述的技巧可以提高在网格中加载数据的性能。您只需执行两个步骤:

    删除网格的sortnamesortorder 选项。大型数据集的排序可能需要时间。否sortname(或sortname: "")表示显示未排序数据。它将提高数据初始加载的性能。 删除网格的data 选项并将其设置在onInitGrid 回调中:
$("#TransactionsGrid").jqGrid(
    datatype: "local",
    hoverrows: false,
    colNames: colHeader,
    colModel: colname,
    rowNum: 10,
    rownumbers: true,
    viewrecords: true,
    caption: "Transaction Details",
    height: "auto",
    gridview: true,
    autoencode: true,
    ignoreCase: true,
    onInitGrid: function () 
        // get reference to parameters
        var p = $(this).jqGrid("getGridParam");

        // set data parameter
        p.data = $.parseJSON(gridData).BuildTransactionsDataTable;
    
);

The demo from the answer 加载 90000 行数据,加载大约需要 52-130 毫秒,具体取决于我使用的 Web 浏览器。在我看来,这是一个好时机。如果没有这个技巧(参见the demo),数据的加载大约需要 1600-11000 毫秒。如果添加数据排序(请参阅one more demo),那么我得到的时间在 2100-29000 毫秒之间。

更新:首先你应该从 javascript 代码中删除所有不需要的东西。

index 属性必须name 属性的值相同。如果您在内部删除index 属性,jqGrid 将创建正确的index 值。所以我强烈建议大家不要在colModel中指定index属性。 我建议您从colModel 中的cmTemplate 项中移动所有常见属性(或最常见的属性)。例如,如果您在 colModel 的所有项目中使用 width: 100,则应删除该属性并添加 jqGrid 选项 cmTemplate: width: 100 ,而不是将具有相同值的属性 width 放置在的 每个 项目中colModel. 我建议您使用the documentation 中的colModel 属性检查表中Default 列中的值。您会发现align: 'left'editable: falsesortable: truestype: "text" 和其他一些属性的放置不需要。我建议您删除这些属性。 如果您有来自后端的数据的本机唯一 ID,我建议您将其用作 rowid。有两个选项:1)您需要向用户显示该列。如果您只需要在 colModel 中添加 key: true 属性 2) 您不需要向用户显示 id。如果您不需要使用数据创建任何隐藏列。取而代之的是,您可以添加localReader: id: "TransactionId" 选项来通知jqGrid 从哪里获取rowid。原生 rowid 的使用对于编辑来说尤其实用。带有rowid 的id 参数将在编辑期间由jqGrid 发送到服务器。我建议您另外使用prmNames: id: "TransactionId" 。在 jqGrid 的情况下,属性的名称为 "TransactionId" 而不是默认名称 "id" 在编辑期间。 用colModelname 属性值填充colNames。你不需要这样做。我建议您在这种情况下根本不要指定colNames 选项。在这种情况下,jqGrid 将使用colModellabel 属性值或name 属性值在内部填充colNames,如果label 不存在。 我建议您在所有数据项中隐藏空值(null""" " 等)值的列。它使用户更容易阅读网格并提高网格的性能。对于 Web 浏览器来说,显示多列的成本要比显示多行的成本高得多。因此隐藏不需要的列可以提高网格的性能。 一个更重要的问题我还没有在演示中解决如下。您使用了错误的 name 属性值。您当前的代码包含具有name: "Employee Name"name: "Avg.Num Of Steps Occur" 的列。重要的是要了解name 属性将用于构建一些内部jqGrid 元素的id 属性并将在选择器中使用。 jQuery 选择器不应包含任何 meta-charackters (!"#$%&'()*+,./:;<=>?@[\]^``|~)。此外,例如 HTML 4 的 id 不能包含空格。见here。我强烈建议您在 name 中仅使用字母 ([A-Za-z])、数字 ([0-9])、连字符 ("-") 或下划线 ("_")。第一个符号应该是一个字母。如果您不遵守规则,您可能会遇到很多问题(排序、搜索等问题)。可能您应该设置label: this.Name 属性并使用一些规则来基于this.Name 构建正确的name 值。您应该在编辑过程中包含带有原始this.Name 属性的属性,以便发送编辑结果与修复name 属性之前相同。

因此,我将您的代码修改为以下内容:http://jsfiddle.net/z1ujyh02/6/。我在下面包含的代码中最重要的部分:

var columnsData = "...", gridData = "...";
var mydata = $.parseJSON(gridData).BuildTransactionsDataTable, existingProperties = ,
    numberTemplate = formatter: 'number', sorttype: 'int',
    dateTemplate = 
        editable: true,
        searchoptions: 
            dataInit: function (el) 
                var self = this;
                $(el).datepicker(
                    dateFormat: 'm/d/yy', maxDate: 0, changeMonth: true, changeYear: true,
                    onSelect: function (dateText, inst) 
                        setTimeout(function () 
                            self.triggerToolbar();
                        , 50);
                    
                );
            
        ,
        editoptions: 
            dataInit: function (el) 
                $(el).datepicker(
                    dateFormat: 'm/d/yy', maxDate: 0, changeMonth: true, changeYear: true
                );
            ,
            readonly: 'readonly'
        
    
    dropdownTemplate = 
        edittype: "select",
        editable: true,
        stype: "select"
    ;

$.each(mydata, function () 
    var p;
    for (p in this) 
        if (this.hasOwnProperty(p) && this[p] !== null && (typeof this[p] === "string" && $.trim(this[p]) !== "")) 
            existingProperties[p] = true;
        
    
);

var colname = [ name: "TransactionId", sorttype: "int", key: true ];
//Loop into the column values collection and push into the array.
$.each($.parseJSON(columnsData).Table1, function () 
    //Check the datatype of the column.
    var cm = 
            name: this.Name,
            hidden: JSON.parse(this.IsHidden) || !existingProperties.hasOwnProperty(this.Name),
            editoptions: this.DefaultValue != null && this.DefaultValue != "" ?  defaultValue: this.DefaultValue  : ,
            editrules:  required: JSON.parse(this.IsRequired) 
        ;
    switch (this.Datatype) 
        case 'number':
            $.extend(true, cm,  template: numberTemplate );
            lastFieldName = cm.name; //Store the fieldName.
            break;
        case 'DateTime':
            $.extend(true, cm,  template: dateTemplate );
            lastFieldName = cm.name;
            break;
        case 'dropdown':
            var values = this.ValueList.slice(0, -1);
            $.extend(true, cm, 
                template: dropdownTemplate,
                editoptions:  value: ":Select;" + values, defaultValue: this.DefaultValue ,
                searchoptions:  value: ":All;" + values 
            ,
            this.ValueType == "F" ?  label: this.ValueId  :  );
            break;
        default:
            break;
    
    if (cm)
    colname.push(cm);
);

//Binding grid Starts.
$("#TransactionsGrid").jqGrid(
    //data: mydata,
    datatype: "local",
    hoverrows: false,
    colModel: colname,
    rowNum: 10,
    rownumbers: true,
    pager: "#TransactionsPager",
    localReader:  id: "TransactionId" ,
    prmNames:  id: "TransactionId" ,
    viewrecords: true,
    caption: "Transaction Details",
    height: "auto",
    gridview: true,
    autoencode: true,
    ignoreCase: true,
    cmTemplate:  width: 100 ,
    onInitGrid: function () 
        // get reference to parameters
        var p = $(this).jqGrid("getGridParam");

        // set data parameter
        p.data = mydata;
    
);

【讨论】:

感谢您的宝贵回复,我还需要简化脚本中使用的开关盒,以便我可以轻松构建对象数组。现在可读性和代码很复杂。 @HbV2:不客气!您写道“我需要简化脚本中使用的 switch case”。我不明白你的意思。可能您应该在有问题的地方发布部分代码。我建议您另外在colModel 中使用templates。见the answer。它可以简化代码。 我更新了问题。除了模板,我还能做些什么让它变得简单。 @HbV2:我稍后会附上我的答案以及如何通过使用列模板来减少/优化的建议。我应该说一下,但这样的更改会减少代码,使其更具可读性和可维护性,但它会减少页面的性能。我最初发布的建议可以提高网格的性能,尤其是在它有很多行的情况下。您通常在网格中有多少行?哪个网络浏览器是您的主要浏览器? 非常感谢。行大约在 1000 到 5000 之间,列大约在 50 到 100 之间。这个网格将是响应式的。我们使用的主要浏览器是 chrome,即 safari、firefox。

以上是关于优化jqgrid中动态创建的colmodel的主要内容,如果未能解决你的问题,请参考以下文章

jqGrid动态列绑定

jqGrid - 将colmodel保存到本地缓存

JQGrid - 动态更改列的宽度

jqGrid 怎么动态控制 multiselect 属性

在js中怎么改变jqgrid行数据

colNames 和 colModel 错误的 JQgrid 长度