2013-03-04 100 views
3

我想有一個可觀察數組,它將在對象被推入時自行排序(如果它將在比較器中使用的任何值進行排序,它會更好功能已更改)。knockout.js排序的可觀察數組

的東西,你可以定義你想要的數組進行排序,然後每次推送被調用時它會如此的排列還是保持有序的推對象添加到正確的位置在數組中,喜歡比較器功能:

var sortedArray = ko.sortedObservableArray(
    function (a,b) { return b - a;}, 
    [1,7,4] 
); // sortedArray will be [1,4,7] 
sortedArray.push([5,2]); // sortedArray will now be [1,2,4,5,7] 

是否有任何圖書館會爲我做這件事,如果沒有,最好的方法是什麼去實現呢?

回答

3

我最終通過延長淘汰賽觀察到陣列創建一個分類觀察到的數組:

ko.sortedObservableArray = function (sortComparator, initialValues) { 
    if (arguments.length < 2) { 
     initialValues = []; 
    } 
    var result = ko.observableArray(initialValues); 
    ko.utils.extend(result, ko.sortedObservableArray.fn); 
    delete result.unshift; 
    result.sort(sortComparator); 
    return result; 
}; 

ko.sortedObservableArray.fn = { 
    push: function (values) { 
     if (!$.isArray(values)) { 
      values = [values]; 
     } 
     var underlyingArray = this.peek(); 
     this.valueWillMutate(); 
     underlyingArray.push.apply(underlyingArray, values); 
     underlyingArray.sort(this.sortComparator); 
     this.valueHasMutated(); 
    }, 
    sort: function (sortComparator) { 
     var underlyingArray = this.peek(); 
     this.valueWillMutate(); 
     this.sortComparator = sortComparator; 
     underlyingArray.sort(this.sortComparator); 
     this.valueHasMutated(); 
    }, 
    reinitialise: function (values) { 
     if (!$.isArray(values)) { 
      values = [values]; 
     } 
     var underlyingArray = this.peek(); 
     this.valueWillMutate(); 
     underlyingArray.splice(0, underlyingArray.length); 
     underlyingArray.push.apply(underlyingArray, values); 
     underlyingArray.sort(this.sortComparator); 
     this.valueHasMutated(); 
    }, 
    reverse: function() { 
     var underlyingArrayClone = this.peek().slice(); 
     underlyingArrayClone.reverse(); 
     return underlyingArrayClone; 
    } 
}; 

可在下列方式使用:

var sortedArray = ko.sortedObservableArray(
    function (a,b) { return a - b;}, 
    [1,7,4] 
); // sortedArray will be [1,4,7] 
sortedArray.push([5,2]); // sortedArray will now be [1,2,4,5,7] 
sortedArray.sort(function (a,b){ 
    return b - a; 
}); // sortedArray will now be [7,5,4,2,1] 
sortedArray.push(6); // sortedArray will now be [7,6,5,4,2,1] 

我唯一的問題是,重新初始化時使用新數組排序的observable數組的方式與重新初始化可觀察數組的排序後的observable數組沒有進行排序相同。爲了解決這個問題,我在已排序的可觀察陣列上添加了一個重新初始化函數:

var sortedArray = ko.sortedObservableArray(
    function (a,b) { return a - b;}, 
    [1,7,4] 
); // sortedArray will be [1,4,7] 

sortedArray([3,2,8]); // this doesn't work correctly, sortedArray will be [3,2,8] 
// instead of [2,3,8] 

// To get around this you can use reinitialise() 
sortedArray.reinitialise([3,2,8]); // sortedArray will be [2,3,8] 
2

試試這個:

var sortedArray = ko.observableArray(); 
sortedArray.subscribe(function() { 
    if (!sortedArray._isSorting) { 
     sortedArray._isSorting = true; 
     sortedArray.sort(function (a, b) { return b - a; }); 
     sortedArray._isSorting = false; 
    } 
}); 

您可以在一個功能包裝這件事,只要你想創造新的分類觀察到的陣列。

+0

您不需要額外的標誌。 JavaScript是隻有一條執行線的語言,沒有線程。所以,這意味着'排序'操作過程中沒有什麼可以改變'observableArray' – Serjio 2013-08-21 07:02:22

+1

@Serjio - 即使單線程代碼也需要關注重入。調用'sortedArray.sort'將會觸發對'sortedArray.notifySubscribers()'的另一次調用,它將以遞歸方式再次調用我們的訂閱回調。 – Brandon 2013-08-22 01:55:27

+0

是的,我明白了。謝謝 – Serjio 2013-08-22 09:17:56