2012-02-08 55 views
3

我有一个项目的集合,我想显示总计以及每个项目的个别百分比。问题似乎是在计算总数时需要父对象的引用。所以我想我会为集合定义一个计算的getTotal,并为该项目定义一个百分比。Knockout - 如何为同一时间的孩子和父母设置计算属性?

function Collection() { 
    var self = this; 
    self.parts = ko.observableArray(); 
    self.getTotal = ko.computed(function() { 
     var total = self.parts.length; 
     return total; 
    }); 
} 

function Part(amount, parent) { 
    var self = this; 
    self.amount = ko.observable(amount); 
    self.parent = parent; 

    self.percentage = ko.computed(function() { 
     return self.amount()/self.parent.getTotal(); 
    }); 
} 

var partsData = [40, 50, 30]; 
var collection = new Collection(); 
for (var i = 0; i < partsData.length; ++i) { 
    collection.parts.push(new Part(partsData[i], collection)); 
} 

ko.applyBindings(collection); 

而我的HTML是

<ul data-bind="foreach: parts"> 
    <li> 
     <p data-bind="text: amount"></p> 
     <p data-bind="text: percentage"></p> 
    </li> 
</ul> 

然而Collection.parts总是空的。出于某种原因推动它不会触发重新计算的项目。

也是这样做的正确方法吗?我现在可以弄清楚如何在集合中同时创建一个observableArray,同时为每个子项提供对父对象的引用。

回答

6
  1. 你的getTotal应该返回金额的总和,而不是零件的数量,对不对?
  2. 您不必将元素逐个推送到零件。你可以做collection.parts($。map([40,50,30],function(el){return new Part(el,collection);});) (我在这里使用jQuery.map)
  3. In一般我认为百分比不属于Part,因为它必须通过一个集合,这是不好的(不必要的依赖)。我会做它,而不是这样:
function ViewModel() { 
    var self = this; 
    self.parts = ko.observableArray([]); 
    self.total = ko.computed(function(){ 
     var s = 0; 
     $.each(self.parts(), function(i, el){s += el.amount();}); 
     return s; 
    }); 
} 

function Part(amount){ 
    this.amount = ko.observable(amount); 
} 

$(function() { 
    var view = new ViewModel(); 
    var parts = $.map([40, 50, 30], function(el){return new Part(el);}); 
    view.parts(parts); 
    ko.applyBindings(view); 
}); 

HTML:

<ul data-bind="foreach: parts()"> 
    <li> 
     <p data-bind="text: amount"></p> 
     <p data-bind="text: amount()/$root.total()"></p> 
    </li> 
</ul> 
+0

这将正常工作。我认为在Part对象上离散表示百分比而不是在视图中计算它是一个好的选择。你做这件事的方式很好。事实上,你甚至可以删除'self.parent',并直接在你的计算observable中直接使用'parent',因为它将包含在你传递给你计算的observable的函数所创建的闭包中。 – 2012-02-08 21:14:21

+0

我同意最初的代码是好的,但如果你只需要显示一个百分比,我宁愿不在Part和Collection之间引入额外的依赖关系。对于其他一些不属于问题组成部分的东西可能会有用。 – 2012-02-08 21:32:03

+0

我之所以把百分比放在零件上是因为它们会随着大量的属性和功能而增长。最终,我打算创建将模仿我的对象模型的Javascript模型,这是有道理的。我想我错过了把()放在计算函数中的属性上,并打破了它。完全称赞罗马。 – 2012-02-08 22:18:16