【问题标题】:KnockoutJS ObservableArray data groupingKnockoutJS ObservableArray 数据分组
【发布时间】:2012-04-10 06:17:23
【问题描述】:

KnockoutJS 是否有一个功能,而我可以采取以下方式:

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

然后在“类型”字段中选择 distinct,产生如下所示的结果:

(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 中是否还有其他内容。

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    在 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/

    这确实会在每次更改时重建索引一次,因此如果您有大量项目,那么您可能希望探索其他方式(手动订阅)以从“索引”数组中添加/删除项目。

    【讨论】:

    • 优秀的答案。你能举个例子如何链接它(分组一组可观察数组)吗?
    • 这是一个很好的例子。谢谢瑞恩尼迈耶。关于连锁。它不想开箱即用。我不得不调整它jsfiddle.net/xuzhke3m
    【解决方案2】:

    我在 jsfiddle 中简化了 RP Niemeyer 的版本,以便在不使用 distinct 函数的情况下做同样的事情。请参考这里: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());
    

    感谢尼迈耶。

    【讨论】:

      【解决方案3】:

      只是想补充一点,如果您两次调用此 .distinct() 方法(可能来自计算的 observable),您将获得两次调用的索引和相关的计算函数 - 冲洗并重复,您将获得你手上的性能问题。

      要解决这个问题,请在函数顶部附近添加以下行:

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

      【讨论】:

        猜你喜欢
        • 2015-05-18
        • 1970-01-01
        • 1970-01-01
        • 2011-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多