2012-03-26 57 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()); 

感谢尼迈耶。

相关问题