2

我有一个对象数组存储在 中observableArray,每个数组项都是 moment.js 日期的对象。

{startDate:momentObject, endDate:momentObject, cycle:null}

我需要计算两件事。一个是startDates之间的平均时间。我认为最简单的方法是计算数组中最早和最晚 startDates 之间的持续时间,并将其除以条目总数。

我还需要两个 startDates 之间的时间段。我想出的一个快速解决方案是这样的:

$.each(dateArray, function(index, item){
    var previousItem = dateArray[index - 1];

    if(previousItem){

      // since these are moment objects, just use the diff method
      return item.cycle = previousItem.startDate.diff(item.startDate, 'days');
    }

    return false;
});

但这需要observableArray按升序排序。所以这是我的问题。

  1. 如何确保每次向其推送新项目时都对其进行observableArray强制排序?
  2. 有没有更好的方法来计算startDates中间周期和中间周期之间的周期?
  3. 也许,我可以在将项目添加到数组而不是循环时计算周期?
4

3 回答 3

5

您可以向 obervableArray 添加订阅事件处理程序,如下所示:

self.MyArray = ko.observable([]);
var myArraySubscription = self.MyArray.subscribe(onMyArrayChange);

function onMyArrayChange(){
    //Remove the subscription before sorting, to prevent an infinite loop
    myArraySubscription.dispose();
    myArraySubscription = null;

    //Force a sort of the array here. 
    self.MyArray.sort();//NOTE: You need to define your sorting logic here...this line is just a placeholder

    //Re-subscribe
    myArraySubscription = self.MyArray.subscribe(onMyArrayChange);
}
于 2013-06-18T02:07:37.270 回答
4

如果您将视图数据绑定到依赖于日期数组的计算 observable,您可以在每次日期数组更新时在数组上运行排序逻辑。

this.dateArray = ko.observableArray([]);

this.sortedDates = ko.computed(function() {
    var dates = this.dateArray();

    //... do sorting stuff on dates ...

    return dates;

}, this);
于 2013-06-17T20:19:30.963 回答
1

另一个使用 Knockout 扩展功能的解决方案是:

  var unwrap = ko.utils.unwrapObservable;

  ko.extenders.sorted = function(target, key) {
    /*

    You may pass in a function, that will be used as the comparison
    function, or a key, that will be used as the attribute upon
    which we will sort.

    The value (unwrapped, if applicable) must have a valueOf() method,
    so we can compare using that.

    */

    var sortFunction;

    if (typeof key === 'function') {
      sortFunction = key;
    } else {
      sortFunction = function(a,b) {
        return unwrap(a[key]) - unwrap(b[key]);
      };
    }

    // We want to prevent our subscription firing when
    // we are already in the process of doing a sort.
    var sorting = false;

    target.subscribe(function sortSubscribe(newValue) {
      if (sorting) {
        return;
      }
      if (target().length > 1) {
        sorting = true;
        // We need to sort the observableArray, not the underlying
        // array. We could do the latter, but then would need to call
        // notifySubscribers() anyway.
        target.sort(sortFunction);
        sorting = false;
      }
    });

    return target;
  };

示例用法是:

foo = ko.observableArray([]).extend({sorted: 'key'})
foo.push({key: 'value1'})
foo.push({key: 'value0'})

foo() --> [{key: 'value0'},{key: 'value1'}]
于 2014-02-25T01:08:22.710 回答