Knockout.js 使用knockout绑定大约5000条记录

Knockout.js 使用knockout绑定大约5000条记录,knockout.js,durandal,ko.observablearray,Knockout.js,Durandal,Ko.observablearray,我正在尝试使用敲除可观测数组在一个网页中显示大约5000条记录,这需要花费大量时间 有没有办法不用分页来处理这个问题 请帮忙 视图模型中的JS代码,数据来自gridData源中的ajax调用: groupGrid.prototype.updateGrid = function (gridDataSource, groupGridOptions) { var self = this; self.ColumnName(groupGridOption.ColumnNa

我正在尝试使用敲除可观测数组在一个网页中显示大约5000条记录,这需要花费大量时间

有没有办法不用分页来处理这个问题

请帮忙

视图模型中的JS代码,数据来自gridData源中的ajax调用:

 groupGrid.prototype.updateGrid = function (gridDataSource, groupGridOptions) {
        var self = this;
        self.ColumnName(groupGridOption.ColumnNameList); //   List of column name available in the data source.
        self.gridData(gridDataSource);    //  taking time while executing this code  
        self.totalRowCount(self.gridData().length);
        self.selectedItems.removeAll();
        self.selectedRowCount(0);
    };
HTML代码:

<tbody class="ngTBody" data-bind="foreach: gridData">
<tr class="ngdatarow">
<td>
    <span class="nameHeader" data-bind="text: $data[$root.ColumnName()[0]], click: $root.gridNameClick" style="cursor: pointer; text-decoration: underline"></span>
</td>
<td>
    <span class="displayBlock" data-bind="text: $data[$root.ColumnName()[1]]"></span>
</td>
<td>
    <span class="displayBlock" data-bind="text: $data[$root.ColumnName()[3]"></span>
</td>
</tr>
</tbody>

最近,我一直在与我的KO应用程序的性能作斗争。我只是在这里补充了另一个问题的答案,带着一些想法:

由此产生的,这里有一个小提琴,显示您不需要太多的延迟-这个演示有3000个项目,并为每个项目生成一个简单的div。根据上面链接的博文,这些项目首先在JS数组中构建,然后再转换为observableArray。因此,我非常确定,在这个阶段,您看到的性能问题很简单,就是KO工作中产生的DOM操作

这并不是对性能问题的真正修复,但它表明,如果您循环数千个项目,并且它使用一种模式,您可以确保在长KO操作之前显示加载微调器,然后将其隐藏,则延迟可能是不可避免的。因此,它至少改善了用户体验

确保可以加载微调器:

// Show the spinner immediately...
$("#spinner").show();

// ... by using a timeout.
window.setTimeout(function() {
    ko.applyBindings(vm)  
}, 1)
隐藏微调器:

<div data-bind="template: {afterRender: hide}">
更新1:

我记得我在用Opera开发机顶盒时使用的一种老技术,即使用DOM操作构建UI。它的速度非常慢,因此解决方案是将大块HTML存储为字符串,并通过设置innerHTML属性来加载字符串。单页应用的早期版本。无论如何,作为我在这方面正在进行的工作的一部分,这里有一个JSFIDLE,它显示了5000个项目通过KO加载,但通过一个中间html计算

换句话说,您从列表中计算HTML,并使用HTML绑定一次性设置它。我已经将这个示例设置为5000项,几乎是即时的

巨大的缺点是,它严重限制了您可以在每个项目内绑定的功能

更新2:

这里有一个小提琴,显示了通过数组索引从项目链接回KO视图模型的一些外观。您可能会使用这样的构造来完成KO支持的大部分事情,但您会失去一些魔力;我认为,你必须自己编写更多的代码

更新3:

这个提琴展示了一种使用超时将每个项目逐个推入列表的技术。通过在推送操作之间放置超时,DOM逐项更新。因此,总体渲染时间仍然相当长,但用户会立即得到反馈:

更新4:

显示上述技术,但通过删除记录做一些有用的事情


我对在浏览器中快速生成数据表做了很多研究。使用foreach和文本绑定的标准淘汰方法非常慢。简化绑定代码可以实现一些改进,如我的示例所示。但生成数据表的最快方法是在JavaScript代码中将其组装为字符串,然后使用innerHTML将其插入DOM。我的例子就是如何做到这一点

在您的情况下,组装数据表的自定义绑定将提供巨大的速度提升。下面是我根据您的示例编写的自定义绑定:

ko.bindingHandlers.myDataTable = {
    init: function () {
        return { controlsDescendantBindings: true };
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        var output = [],
            value = valueAccessor(),
            columns = ko.unwrap(value.columns),
            column1 = columns[0],
            column2 = columns[1],
            column3 = columns[2],
            data = ko.unwrap(value.data),
            dataLength = data.length,
            clickFunction = value.click;
        output.push('<table><tbody class="ngTBody">');
        for (var i = 0; i < dataLength; ++i) {
            output.push('<tr class="ngdatarow"><td><span class="nameHeader" data-index="');
            output.push(i + '">');
            output.push(data[i][column1]);
            output.push('</span></td><td><span class="displayBlock">');
            output.push(data[i][column2]);
            output.push('</span></td><td><span class="displayBlock">');
            output.push(data[i][column3]);
            output.push('</span></td></tr>');
        }
        output.push('</tbody></table>');
        element.innerHTML = output.join('');
        $(element).on('click', 'span.nameHeader', function (event) {
            var index = event.target.getAttribute('data-index');
            if (index) {
                clickFunction(data[index], event);
            }
        });
    }
};
为了进行比较,我将以下两种小提琴组合在一起:

使用foreach。在我的计算机上渲染表格需要2到3秒。 使用自定义绑定。渲染表格的速度几乎快了25倍。
我还创建了一个包含click绑定并使用ko.ApplyBindingsToDescents的应用程序,但它比上面的示例要长得多,因为它必须设置5000个事件处理程序,而不是一个。

到目前为止,您有什么?您的视图模型是什么样子的?你的装订是什么样子的?通常,如果您通过逐个添加项来填充数组,那么它的速度会很慢。如果你可以将它们加载到一个普通的JS数组中,然后用这个.myobsarrayjsarray填充整个可观察对象,那么速度会快得多。Ryan Niemeyer的这篇文章也值得一读。我已经找到了这个问题,发现这个问题通常不是敲除,这取决于某些浏览器呈现包含这么多元素的页面所需的时间。当然,动态更新许多元素会使事情更加困难,但再次强调,这不是击倒的问题。。。我认为这是对淘汰赛的滥用。退后一步,有时你可能想要或需要推迟多久可以观察到的更新。可以在淘汰赛3.1.0+和KO的早期版本中使用。我可以提出其他建议,但我将在黑暗中拍摄。如果你不想让这个问题被否决,你需要更加具体,谈谈你的应用程序正在做什么,你认为可能会导致性能问题。说出大约5000条记录是没有帮助的。