2011-06-22 103 views
13

有沒有更好的(內置?)方法來混合observableArray和關聯數組?ko.observableArray支持關聯數組

viewModel = { 
    a: ko.observableArray(), 
    a_assoc: {}, 
    add_item: function(i) { 
     if (typeof this.a_assoc[i] == 'undefined') { 
      this.a.push(i); 
      this.a_assoc[i]=1; 
     } 
    } 
} 

viewModel.add_item('bla'); 

回答

8

通常情況下,你會做這樣的事情在淘汰賽:

var viewModel = { 
    a: ko.observableArray(["a","b","c","d"]), 
    add_item: function() { 
     this.a.push("new" + this.a().length); 
    } 
}; 

viewModel.a_assoc = ko.dependentObservable(function() { 
    var result = {}; 
    ko.utils.arrayForEach(this.a(), function(item) { 
     result[item] = 1; 
    }); 
    return result; 
}, viewModel); 

所以,你有你的陣列映射到一個對象dependentObservable。請注意,每次更新原始數組時,對象都會重建。因此,它不如您的文章中的方法高效,但除非您的對象實質性大,否則它會引起性能問題,這是值得懷疑的。

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

+1

謝謝RPN。我的數據集將增長到2K所以不,我不認爲性能是一個問題。順便說一句,有沒有在線ko.utils的參考? –

+2

目前還沒有關於utils的文檔。目前最好的資源來自我的博客:http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html –

+0

真棒。謝謝! –

1

我認爲這是最好使用關聯數組引擎蓋性能下。你也(如你所暗示的)需要使用observableArray來跟蹤更改(因爲這就是淘汰賽的工作原理)。

如果你正在尋求一個'挖空友好'關聯數組,你可能需要一種方法來跟蹤對項目的改變(從而影響依賴關係鏈)。

http://jsfiddle.net/rz41afLq/2/

這就是我想出了適合我的需要。基本上,您在observableArray中存儲了一個鍵值對,並使用標準關聯數組來存儲用於查找的副本。

// VIEW MODEL 
var viewModel = { 

    // we have to use observable array to track changes 
    items: ko.observableArray([]), 

    // also use associative array for performance 
    _assoc: {}, 

    update_item: function(key, value) { 

     // use a true assoc array for performance 
     // _assoc[key] = ko.observable(value) 
     if (viewModel._assoc[key]) 
     { 
      // update observable (overwriting existing item) 
      viewModel._assoc[key].value(value); 
     } 
     else { 
      // Important: See how we wrap value with an observable to detect changes 
      this.items.push(viewModel._assoc[key] = { key: key, value: ko.observable(value) }); 
     } 
    } 
}; 

所以你保存你的狗是這樣的:

update_item('dogs', ['kim', 'abbey', 'goldie', 'rover']); 
update_item('dogs', ko.observableArray(['kim', 'abbey', 'goldie', 'rover'])); 

(第二隻需要如果你是在狗的名單上調用pop()push()和要更新的UI規劃你。當然可以撥打update_item在任何時候完全更新該物品,在這種情況下它不需要可觀察)

要查找值,您可以動態創建一個計算值以獲取它:

var dogs = getValue('dogs'); 

然後,一旦在關聯數組中索引爲「狗」的值發生變化,則可觀察的dogs()將更新(並且可以鏈接)。這dogs observable可以綁定到用戶界面當然

var getValue = function(key) { return ko.pureComputed(function() 
{ 
    // reevaluate when item is added or removed to list 
    // not necessary if the value itself changes 
    viewModel.items();              

    var item = viewModel._assoc[key]; 
    return (item == null) ? null : item.value(); 

}, viewModel);