Knockout - 如何同时设置子级和父级的计算属性?

发布于 2025-01-04 11:58:36 字数 1161 浏览 1 评论 0原文

我有一个项目集合,我想显示每个项目的总数以及单独的百分比。问题似乎是我在计算总数时需要父对象的引用。所以我想我将为 Collection 定义一个计算的 getTotal 并为该项目定义一个百分比。

    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 始终是空的。由于某种原因推动它不会触发重新计算的项目。

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

I have a Collection of items that I would like to display the Total as well as individual Percentage of each item. The problem seems to be that I need a reference of parent object when computing the total. So I figured I'll define a computed getTotal for the Collection and a percentage for the item.

    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);

And my HTML is

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

However the Collection.parts is always empty. For some reason push it not triggering the items to be recalculated.

Also is this the right way for doing this? I could now figure out how I could simultaneously create an observableArray in the Collection while giving each child item a reference to the parent object.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷爱 2025-01-11 11:58:36
  1. 您的 getTotal 应该返回金额总和,而不是部分数量,对吗?
  2. 您不必将元素一一推入零件。你可以这样做 collection.parts($.map([40, 50, 30], function(el){return new Part(el, collection);});)
    (我在这里使用 jQuery.map)
  3. 一般来说,我认为百分比不属于 Part,因为那时它必须传递一个集合,这是不好的(不必要的依赖)。我会这样做:
函数 ViewModel() {
    var self = this;
    self.parts = ko.observableArray([]);
    self.total = ko.compulated(function(){
        var s = 0;
        $.each(self.parts(), function(i, el){s += el.amount();});
        返回 s;
    });
}

函数部分(金额){
    this.amount = ko.observable(amount);
}

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

网页:

<ul data-bind="foreach: parts()">
    <li>
        <p data-bind="text: amount"></p>
        <p data-bind="text: amount() / $root.total()"></p>
    </li>
</ul>
  1. Your getTotal is supposed to return sum of amounts, not number of parts, right?
  2. Your don't have to push elements to parts one by one. You can do collection.parts($.map([40, 50, 30], function(el){return new Part(el, collection);});)
    (I use jQuery.map here)
  3. In general I think percentage doesn't belong to Part, since then it has to be passed a collection, which is bad (unnecessary dependency). I would do it this way instead:
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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文