JqG​​rid性能 - setRowData滞后

时间:2015-05-16 05:42:31

标签: performance jqgrid

当网格有300行,30个cols和4个冻结cols时,

setRowData大约需要5秒钟。

$("#tbl").jqGrid({
    gridview: true,
    url: '../controller/GetData',
    datatype: "json",
    rowNum: pageSize,
    viewrecords: true,
    loadtext: '',
    loadui: 'disable',
    rowList: [1000, 2000, 3000],
    width: $(window).width() - LeftMargin,
    shrinkToFit: false,
    pager: '#dvPager',
    pagerpos: 'left',
    colNames: GetColNames(selectedViewName, viewCols),
    colModel: GetColModel(selectedViewName, viewCols),
    cmTemplate: {
        title: false
    },
    recordtext: "Displaying {0} - {1} of {2}",
    rowattr: function (rowData) {

    },
    //onCellSelect: function (rowid, iCol, cellcontent, e) {
    //    e.stopPropagation();
    //    proto.editcell(rowid, iCol, cellcontent, e);
    //},
    loadComplete: function (data) {..},
    onPaging: function (data) {..},
    serializeGridData: function (postData) {..}
    });

你能指导一下性能调整技巧吗?

在GetColModel中,我们按如下方式绑定列 -

'Discount': {
                name: 'Discount', index: 'Discount', width: colModelWidthDict['Discount'], title: false, sortable: false, resizable: colResizable, hidden: !bReadCalculationSellInfo,
                formatter: function (cellValue, option, rowObject) {
                    if (rowObject.level == 0 || (rowObject.Flag == 0 && (rowObject.Discountable && rowObject.Discountable.toLowerCase() == 'no')))
                        return '';
                    else {
                        if (!proto.IsReadOnly(rowObject) && ((rowObject.Flag == 0 && (rowObject.Discountable && rowObject.Discountable.toLowerCase() == 'yes')) || rowObject.Flag > 0))
                            
                            return proto.GetControls("Discount", option.rowId, "Numeric", rowObject.Discount, 6, 90)
                        else
                            return '<span class="amt">' + cellValue + '</span>';
                    }
                },
                unformat: function (cellValue, option) {
                    return cellValue;
                },
                cellattr: function (rowId, val, rowObject, cm, rdata) {
                    if (parseInt(rowObject.PPPChngDisc) == 1)
                        return ' style="color:red"';
                }
            }
// colModel的代码 -

之上的1列

1 个答案:

答案 0 :(得分:0)

通常,您应该更喜欢仅修改少量行。如果您修改一行,则Web浏览器必须重新计算网格的所有其他行(500行)的位置。在修改300行的情况下,意味着Web浏览器的操作为300 * 500。

如果您填写整个网格并使用gridview: true选项,则jqGrid会在字符串数组中为网格主体的所有数据放置。在以字符串格式准备所有信息后,jqGrid将整个网格体作为一个操作。它只是指定innerHTML tbody属性的一个属性。因此,重新加载整个网格更有效,以便使用setRowData修改循环中的多行网格。

所以我建议你在你的情况下重新加载网格。

此外,您应该考虑减少网格页面中的行数。如果您使用rowNum: 500,您只需多次降低页面性能,而不会给用户带来任何好处。用户只能看到大约20行数据。只有当用户滚动时,他/她才能看到另一个信息。以同样的方式,用户可以单击下一页按钮。持有500行强制Web浏览器会造成很多不必要的工作。从500浏览器修改第一行必须重新计算所有500行的位置。即使用户将鼠标移到一行上,Web浏览器也会更改悬停行的类,并且必须重新计算500行中所有其他行的位置,而行不可见。

还有一句话。 jqGrid 4.6中冻结列的实现很慢。从2014年底开始发布4.7.1并更改Lisanse并制作jqGrid商业广告我基于jqGrid 4.7开发free jqGrid作为fork(有关详细信息,请参阅the readme)。我在fork中实现了很多更改和新功能。最近的变化包括许多冷冻柱功能的改进。如果您加载免费的jqGrid或者只是通过包含相应的URL(请参阅the wiki)直接从GitHub尝试它,您将看到冻结列的性能得到显着改善。此外,冻结列现在支持所有编辑模式下的行和单元格编辑。我计划很快发布免费的jqGrid 4.9。所以我建议你试试。

更新:您发布了以下评论中使用的代码。我看到了Process函数实现中的主要问题,该函数将在网格上的<input>字段中进行更改时调用。我建议你试试这样的东西:

function Process(contrl) {
    var $cntrl = $(contrl),
        $td = $cntrl.closest("tr.jqgrow>td"),
        $tr = $td.parent(),
        rowId = $tr.attr("id"),
        newValue = $cntrl.val(),
        $grid = $("#list"),
        p = $grid[0].p,
        colModel = p.colModel,
        columnName = colModel[$td[0].cellIndex].name, // name of column of edited cell
        localRowData = $grid.jqGrid("getLocalRow", rowId),
        iColTotal = p.iColByName.total;

    // modify local data
    localRowData[columnName] = newValue;
    localRowData.total = parseInt(localRowData.quantity) * parseFloat(localRowData.unit);

    // modify the cell in the cell (in DOM)
    //$grid.jqGrid("setCell", rowId, "total", localRowData.total);
    $($tr[0].cells[iColTotal]).text(localRowData.total);
    return false;
}

一个可以改善代码的事件,根本不使用setCell。了解本地网格以JavaScript对象的形式保存数据非常重要。对数据的访问非常快。您可以修改数据,而不会产生DOM元素的任何副作用。在上面的代码中,我使用closestparent在行的DOM中仅使用 relative 搜索。它运作得非常快。我建议将$("#list")保存在Process的变量 之外(在外部函数中移动var $grid = $("#list")),然后使用$grid变量。它将非常快速地访问页面的DOM。行localRowData = $grid.jqGrid("getLocalRow", rowId)引用引用到内部JavaScript数据对象,该对象表示行的内部数据。通过localRowData[columnName] = newValue;localRowData.total = ...修改数据,我们可以完成一半的工作。只需要在单元格Total上更改DOM中的值。我使用了iColByName,它存在于GitHub上的最新免费jqGrid源代码中。它只按列名称获取colModel中的列索引。如果使用更旧的jqGrid,可以选择相同的信息。第$($tr[0].cells[iColTotal]).text(localRowData.total);行显示了如何手动分配单元格中的数据。这是最快速的方法,但是在没有使用格式化程序的情况下分配数据 。对于更常见的情况(例如,在冻结的“总”列的情况下),可以使用上面的注释行:$grid.jqGrid("setCell", rowId, "total", localRowData.total);