2012-03-26 56 views
14

確實KnockoutJS有一個特點,而我可以採取類似:KnockoutJS ObservableArray數據分組

var myArray = ko.observableArray([ 
     { name: "Jimmy", type: "Friend" }, 
     { name: "George", type: "Friend" }, 
     { name: "Zippy", type: "Enemy" } 
    ]); 

然後選擇「類型」字段不同,產生的結果看起來像這樣:

(pseudo code) 
    var distinct = myArray.distinct('type') 
     // Returns array of two arrays 
     // distinct[0] is an array of type=Friend 
     // distinct[1] is an array of type=Enemy 

我知道ko.utils.arrayGetDistinctValues,但那並不完全符合我的要求。我也意識到我可以使用ko.utils.arrayGetDistinctValues編寫幾個循環來獲得我想要的內容,我只是想知道是否還有其他東西會烘焙到我忽略的KnockoutJS中。

回答

33

爲了使這更容易,KO中沒有其他任何內容。

有很多方法可以使這項工作。例如,您可以將observableArrays擴展爲具有distinct函數。然後,你可以創建你喜歡observableArray:

this.people = ko.observableArray([ 
     new Person("Jimmy", "Friend"), 
     new Person("George", "Friend"), 
     new Person("Zippy", "Enemy") 
]).distinct('type'); 

distinct功能可能看起來像:

ko.observableArray.fn.distinct = function(prop) { 
    var target = this; 
    target.index = {}; 
    target.index[prop] = ko.observable({});  

    ko.computed(function() { 
     //rebuild index 
     var propIndex = {}; 

     ko.utils.arrayForEach(target(), function(item) { 
      var key = ko.utils.unwrapObservable(item[prop]); 
      if (key) { 
       propIndex[key] = propIndex[key] || []; 
       propIndex[key].push(item);    
      } 
     }); 

     target.index[prop](propIndex); 
    }); 

    return target; 
};  

它支持鏈接,所以你可以調用distinct多次以不同的屬性。

樣品在這裏:http://jsfiddle.net/rniemeyer/mXVtN/

但這一次重建的每一個變化的指標,因此,如果你有一個龐大的項目列表,然後你會想可能探索其他方式(手動訂閱)添加/刪除項目來自「索引」數組。

+0

卓越的答案。你能舉一個例子來說明如何鏈接它(分組一組可觀察數組)嗎? – tmg 2015-01-16 15:45:03

+0

這是一個很好的例子。謝謝你,瑞恩尼邁耶。關於鏈接。它不想開箱即用。我不得不調整它http://jsfiddle.net/xuzhke3m/ – forgotpw1 2015-06-01 23:29:35

3

只是想補充一點,如果你兩次調用這個.distinct()方法(就像可能來自一個計算的觀察值),你會得到索引和相關的計算函數兩次 - 沖洗和重複,你有一個性能問題在你手上。

要排序了這一點,添加此線附近的函數的頂部:

if (target.index && target.index[prop]) return target; //Group by already set up, bail out. 
7

我已經簡化了RP尼邁耶在的jsfiddle版本做同樣不使用獨特的功能。請參考這裏:jsfiddle

<ul data-bind="foreach: choices"> 
<li> 
    <h2 data-bind="text: $data"></h2> 
    <ul data-bind="foreach: $root.people"> 
     <!-- ko if: $parent === type() --> 
     <li data-bind="text: name"></li> 
     <!-- /ko --> 
    </ul> 
    <hr/> 
</li> 

var Person = function(name, type) { 
    this.name = ko.observable(name); 
    this.type = ko.observable(type);  
} 

var ViewModel = function() { 
    var self = this; 
    this.choices = ["Friend", "Enemy", "Other" ]; 
    this.people = ko.observableArray([ 
      new Person("Jimmy", "Friend"), 
      new Person("George", "Friend"), 
      new Person("Zippy", "Enemy") 
    ]); 

    this.addPerson = function() { 
     self.people.push(new Person("new", "Other")); 
    }; 

    this.removePerson = function(person) { 
     self.people.remove(person); 
    }; 
}; 


ko.applyBindings(new ViewModel()); 

感謝尼邁耶。

相關問題