2012-03-17 60 views
1

我對Knockout.js很陌生,現在面臨的情況是我不確定如何處理它。問題是:我收到了一堆我通過ajax檢索的對象。其結果將是有點像這樣:如何使用knockout.js管理和呈現嵌套數組?

var Objects = [ { id: 0, name: "Foo", type: "A" }, 
       { id: 1, name: "Bar", type: "B" }, 
       { id: 1, name: "Bar", type: "A" }, ... ]; 

我到目前爲止已經完成(簡體):

var ViewModel = function() { 
    var self = this; 
    self.objects = ko.observableArray(Objects); 
}; 

現在我需要使這些對象在不同的​​列表取決於它們的「類型」。所以有一個「A」類型的對象列表和一個類型爲「B」類型的對象列表(目前有五種類型,但未來可能會添加更多)。

我想出這個(工作)解決方案:

var ViewModel = function() { 
    var self = this; 
    self.objects = ko.observableArray(Objects); 

    self.objectsA = ko.computed(function() { 
     return ko.utils.arrayFilter(self.objects(), function(item) { 
      return (item.type == 'A'); 
     }); 
    }); 

    self.objectsB = ... 
    self.objectsC = ... 
}; 

在我實際的觀點:

<h1>Type A</h1> 
<ul class="typeA" data-bind="template: { name: 'object', foreach: objectsA }"></ul> 

<h1>Type B</h1> 
<ul class="typeB" data-bind="template: { name: 'object', foreach: objectsB }"></ul> 

有沒有更好的辦法來解決這個問題呢?這有效,但它有點難看,並不真正動態,並且包含很多重複。

回答

5

綁定在computed observable內部執行。這意味着你可以選擇使用一個簡單的功能,如果你願意,它可以採用參數而不是實際的computed observable

這意味着您可以簡化它歸結爲:

var ViewModel = function() { 
    var self = this; 
    self.objects = ko.observableArray(Objects); 

    self.filterByType = function(type) { 
     return ko.utils.arrayFilter(self.objects(), function(item) { 
      return (item.type === type); 
     }); 
    }; 
}; 

隨後,針對其綁定想:

<h1>Type A</h1> 
<ul class="typeA" data-bind="template: { name: 'object', foreach: filterByType('A') }"></ul> 

<h1>Type B</h1> 
<ul class="typeB" data-bind="template: { name: 'object', foreach: filterByType('B') }"></ul> 

你的UI現在將更新每當陣列進行操作(項添加/刪除)。但是,如果您要在運行中編輯type,則需要將type作爲要更新的計算可觀察值的觀察值(以您的原始方法或以此方式進行更新)。

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

+0

謝謝,這使得更清晰。我要去這個! – Niko 2012-03-17 18:46:21

1

你可以只讓淘汰賽做過濾這樣的:

<h1>Type A</h1> 
<ul class="typeA" data-bind="template: { name: 'object', foreach: objects }"> 
    <li data-bind="if: type = 'A'"><!--whatever mark-up you wanted here--></li> 
</ul> 

然後做其他類型相同。或者,你甚至可以讓你ViewModel擁有一個類型的數組,並用一個模板完成整個事情。

編輯:包括RP尼邁耶的答案,你可以這樣做:

var ViewModel = function() { 
    var self = this; 
    self.objects = ko.observableArray(Objects); 
    self.types = ["A","B","C","D"]; 

    self.filterByType = function(type) { 
     return ko.utils.arrayFilter(self.objects(), function(item) { 
     return (item.type === type); 
     }); 
    }; 
}; 

<!-- ko foreach types --> 
    <h1> Type <span data-bind="text: $data"></h1> 
    <ul data-bind="{attr: {class = 'type' + $data}, template: { name: 'object', foreach: filterByType($data)}}"></ul> 
<!-- /ko --> 

現在加入E型是一個簡單的加上「E」到你的類型數組。

+0

你的意思是,像兩個嵌套的foreach循環?那可能嗎? – Niko 2012-03-17 18:43:24

+0

@妮科:是的。有可能的 – 2012-03-17 19:30:28