2

在我的 viewModel 上,我有一个名为“bays”的可观察数组,其中包含一个或多个“bay”对象。然后每个“bay”对象包含一个名为“products”的可观察数组,该数组可以包含“product”对象。我的标记看起来像:

<div data-bind="foreach: bays">
    <div class="bay" data-bind="foreach: products">
        <div class="product">
        <!-- Product innards -->
        </div>
    </div>
</div>

如果产品对象从一个托架移动到另一个托架,则产品元素以及其中的所有内容似乎都被破坏然后重新创建,如以下 jfiddle 所示:http: //jsfiddle.net/mXyzs/20 /

由于我的应用程序可以一次在托架之间移动数百个产品,并且必须重新创建它们,这会导致性能问题。有什么方法可以让淘汰赛重新使用现有的产品 html,因为支持它们的对象没有改变,而不是破坏产品元素并重新创建它们?

4

2 回答 2

1

从 Knockout 版本 2.2.0 开始,foreach绑定将检测移动的项目,并且不会为这些项目重新渲染 UI。但是在您的情况下,您将项目从一个数组移动到另一个数组,因此此优化不适用(因为它仅适用于单个foreach绑定)。

为了利用foreach的能力,我们可以将结构展平为单个数组。

var result = [];
ko.utils.arrayForEach(viewModel.bays(), function(bay) {
    ko.utils.arrayForEach(bay.products(), function(product) {
        product.bay(bay);
        result.push(product);
    });
});

如果我们将 acomputed用于展平列表,我们可以在单个foreach绑定中引用它。

<div data-bind="foreach: flattenedProducts">
    <div class="product">
    <!-- Product innards -->
    </div>
</div>

使用这种方法,虽然产品会按bay排序,但所有产品div都是兄弟。因此,您将无法拥有div每个海湾。

示例:http: //jsfiddle.net/mbest/3ZUxZ/

于 2013-03-08T00:05:44.207 回答
0

从外观上看,产品元素并没有被重新创建。我向您的产品对象添加了一个 created 属性

var product = function (data) {
    this.name = ko.observable(data.name);  
    this.created = new Date();
};

单击“移至托架”按钮时,创建日期似乎没有改变。它只是被添加到另一个可观察数组中并且该元素被绘制。

一件事我不会经历。如果您正在执行此推送到可观察数组或从循环中的可观察数组中弹出或其他操作,则成本很高,并且您会看到性能问题。

Ryan Neimeyer 在这里谈到了这个http://www.knockmeout.net/2012/04/knockoutjs-performance-gotcha.html

希望有帮助!干杯! 苏杰

于 2013-03-07T20:49:12.327 回答