2015-02-23 74 views
1

我有一個項目列表(約100項),它們顯示在列表中。 還有一個規定可以應用幾個過濾器。 我正在使用knockoutJS進行數據綁定。當前的實現是像這樣:如何使用knockoutjs實現高效過濾器

var vmModel = function() { 
      var self = this; 
      self.items = ko.observableArray([]) 
      self.filter1 = ko.observable() 
      self.filter2 = ko.observable() 
      self.filter3 = ko.observable() 
      self.filteredItems = ko.computed(function(){ 
       var allItems = self.items() 
       if (self.filter1()) { 
        allItems = ko.utils.arrayFilter(allitems, 
            function(item) {return "some condition";})} 
       ... 
       Other filters 
       ... 
       }) // end of computed function 
      })// end of vmModel 

在我的HTML

<ul data-bind="foreach: filteredItems"> 
    <li data-bind="text: some data"></li> 
</ul> 

每當過濾器的一個改變整個filteredItems被重新計算。因此,當用戶設置filter1,然後設置filter2時,filter1將應用於100個項目。然後,再次爲100個項目應用filter1和filter2。 我想知道是否有更有效的方法來應用過濾器?即重新使用以前的過濾結果?

+1

似乎你低估了現代設備的計算能力。唯一能讓事情變得更流暢的真正功能 - 'rateLimit'你的'computed'(http://knockoutjs.com/documentation/rateLimit-observable.html) – 2015-02-23 09:58:37

+1

而不是每個過濾器都使用'ko.utils.arrayFilter'你最好有一個for循環,然後根據你的過濾器篩選每個項目。這意味着如果應用了多個過濾器,那麼在所有項目中仍然只有一個循環。正如f_martinez所說,rateLimiting也可以使用,但這意味着過濾器不會立即應用,這可能是您不想要的。 – 2015-02-23 10:43:34

+0

@WayneEllery我想我正在做同樣的事情。 問題在於,當您應用第二個過濾器時,會調用相同的循環,然後將filter1和filter2應用於vanila列表項。 – pravin 2015-02-23 17:29:29

回答

0

KO知道你在計算值中使用了多個Observable值,但它不知道爲什麼。我認爲你不能指定將你的代碼的特定部分應用於可觀察的更改事件。

我看到要做到這一點(但我認爲這很醜陋)的唯一方法是將你的價值存儲到一個私有變量(不可觀察,正確的標準JS Var)。當計算結果被調用時,您會將新變量與最新變量進行比較。如果不同,則應用過濾器並將新值存儲在私有變量中。

+0

你可以請解釋一下, 假設filteredList1 ==與filter1項目,然後當我添加另一個過濾器,filter2我添加過濾器? filteredList1或原始列表項? 在這兩種情況下,filteredList1和filteredList2將不會相同。 同時逐項比較它們並不是我想要的。 – pravin 2015-02-23 17:35:05

0

您可能需要使用Knockout Projections

它提供了有效的地圖和過濾功能:

這個庫的關鍵點是,這些轉變都是有效的進行。具體而言,執行映射的回調函數僅在嚴格需要時纔會調用(通常,這僅適用於新添加的項目)。將新項目添加到源數據時,我們不需要重新映射現有數據。當您重新排列源數據時,輸出順序會相應更改,而不會重新映射任何內容。

這種效率可能沒有多大關係,如果你只是平方數, 但是當你映射的自定義對象的複雜的嵌套圖表,它 可能重要的是與 工作的最少執行每個映射更新。