2013-02-26 56 views
2

在我的viewModel上我有一個名爲'bays'的可觀察數組,其中包含一個或多個'bay'對象。每個'bay'對象都包含一個名爲'products'的可觀察數組,它可以包含'product'對象。 隨着我的標記看起來像:Knockout.js - 停止在foreach循環中渲染元素

<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,因爲支持它們的對象不會改變,而不是破壞產品元素並重新創建它們?

+0

http://jsfiddle.net/mXyzs/16/我添加了一個惱人的警報,但你應該看到的是,對象只創建一次。 – Joe 2013-02-26 19:55:30

+1

一個簡單的方法來檢查它們是否被重新創建。使用'data-bind =「text:new Date()」'。這將顯示元素創建的時間。而不是使用惱人的警報。 – 2013-02-26 22:11:19

+0

@Joe我編輯了我的問題和我的jfiddle,因爲我意識到我有點不清楚。我指的是頁面上的產品元素被銷燬,然後在新的托架中再次創建它們,儘管支持綁定的產品對象沒有更改。 – Ric 2013-02-27 12:05:02

回答

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); 
    }); 
}); 

如果我們用一個computed爲扁平列表,大家可以參考一下,在一個單一的foreach結合。

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

使用這種方法,雖然產品將由海灣進行排序,所有的產品div旨意是兄弟姐妹。所以你不能有每個海灣div

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

0

從外觀上看,產品元素不會被重新創建。我在產品對象中添加了創建的屬性

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

單擊移動到托架按鈕時,創建的日期似乎沒有改變。它僅僅被添加到另一個可觀察數組中,並且該元素被繪製。

有一件事我不會通過。如果你這樣做推動到一個可伸縮陣列或從一個循環中的可觀察數組彈出或什麼,它是昂貴的,你會看到一個性能問題。

瑞安Neimeyer這個位置http://www.knockmeout.net/2012/04/knockoutjs-performance-gotcha.html

希望幫助洽談! 乾杯! Suj