2011-06-22 36 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);