【问题标题】:Computed Observable Array from Observable Arrays从可观察数组计算出可观察数组
【发布时间】:2016-11-03 05:44:23
【问题描述】:

我正在使用 Knockout 做一些我认为很简单的事情。我是 Knockout 和 JavaScript 的新手,因此卡住了。任何帮助将不胜感激。以下是手头的问题。

我有三个数组形式的产品库存(打开、关闭、交付),我想以数组的形式计算已售产品库存。实际数据有点复杂。这是我的数据

的简化版
var OpeningGasInventories = [{
  Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 1, 
  ShiftId: 1
}, {
 Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 2, 
  ShiftId: 1
}];

var ClosingGasInventories = [{
  Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 1, 
  ShiftId: 1
}, {
 Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 2, 
  ShiftId: 1
  }];


var DeliveredGasInventories = [{
  Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 1, 
  ShiftId: 1
}, {
 Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 2, 
  ShiftId: 1
  }];

 var SoldGasInventories = [{
  Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 1, 
  ShiftId: 1
}, {
 Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 2, 
  ShiftId: 1
  }];

 var  GasProductSales= [{
  Id: 1,
  CashPrice: 1.919,
  CreditPrice: 0,
  VolumeCashSale: 0,
  VolumeCreditSale: 0,
  AmountCashSale: 0,
  AmountCreditSale: 0,
  GasProductId: 1,
  GasProductName: "Regular",
  ShiftId: 1
}, {
  Id: 2,
  CashPrice: 2.379,
  CreditPrice: 0,
  VolumeCashSale: 0,
  VolumeCreditSale: 0,
  AmountCashSale: 0,
  AmountCreditSale: 0,
  GasProductId: 2,
  GasProductName: "Premium",
  ShiftId: 1
}];

以下是我的 Knokcout 代码,用于计算每个库存的总计并计算已售库存数组

 var AppViewModel = function() {
 var self = this;

   self.OpeningGasInventories = ko.mapping.fromJS(OpeningGasInventories);
   self.ClosingGasInventories = ko.mapping.fromJS(ClosingGasInventories);
   self.DeliveredGasInventories =    ko.mapping.fromJS(DeliveredGasInventories);
  self.SoldGasInventories = ko.mapping.fromJS(SoldGasInventories);
  self.GasProductSales = ko.mapping.fromJS(GasProductSales);


 self.TotalOpeningGasInventory = ko.computed(function() {

        // Now calculate the sum of all Open Gas inventories
        var total = 0;
        self.OpeningGasInventories()
            .forEach(function(item, index) {
                total += +item.Volume() || 0;
            });

        return total.toFixed(0);
    });

    //Compute total of closing gas inventory
    self.TotalClosingGasInventory = ko.computed(function() {

        // Now calculate the sum of all Open Gas inventories
        var total = 0;
        self.ClosingGasInventories()
            .forEach(function(item, index) {
                total += +item.Volume() || 0;
            });

        return total.toFixed(0);
    });


    //Compute total of Delivered gas inventory
    self.TotalDeliveredGasInventory = ko.computed(function() {            
        var total = 0;
        self.DeliveredGasInventories()
            .forEach(function(item, index) {
                total += +item.Volume() || 0;
            });

        return total.toFixed(0);
    });

    //Compute total of Sold gas inventory
    self.TotalSoldGasInventory = ko.computed(function() {            
        var total = 0;           
        self.SoldGasInventories()
            .forEach(function(item, index) {
                console.info("Volume is " + item.Volume());
                total += +item.Volume() || 0;
            });           
        return total.toFixed(0);
    });

   self.SoldGasInventories = ko.computed(function() {            
        //we know all the four arrays are in same order and of same length 

        for (var i = 0; i < self.SoldGasInventories().length; i++) {                          

            self.SoldGasInventories()[i]
                .Volume = parseFloat(self.OpeningGasInventories()[i].Volume()) +
                parseFloat(self.DeliveredGasInventories()[i].Volume()) -
                parseFloat(self.ClosingGasInventories()[i].Volume());          

        }        

        return self.SoldGasInventories();
    });
 };

问题:如果我评论最后一个计算函数 self.SoldGasInventories 则所有数组总数都被计算得很好。最后一个函数假设计算了 SoldGasInvetories 数组,但它没有像我预期的那样工作。一旦我取消注释此函数,则不会调用 self.TotalSoldGasInventory。 我创建了一个JSFIDDLE 请检查并帮助我解决我的问题。谢谢一百万..

【问题讨论】:

  • 这是因为在SoldGasInventories() 中,您不是更新 observable,而是用值替换它。尝试.Volume(...) 而不是.Volume = ...。请参阅jsfiddle.net/8nj31seh/45(虽然不确定它是否正确计算了更改后的值)

标签: knockout.js


【解决方案1】:

您的最后一个计算值不会返回计算值,而是更新其他 observables。

self.UpdateSoldGasInventoriesVolumes = ko.computed(function() {
    //we know all the four arrays are in same order and of same length
    for (var i = 0; i < self.SoldGasInventories().length; i++) {
        self.SoldGasInventories()[i].Volume(
            parseFloat(self.OpeningGasInventories()[i].Volume()) +
            parseFloat(self.DeliveredGasInventories()[i].Volume()) -
            parseFloat(self.ClosingGasInventories()[i].Volume())
        );
    }
});

【讨论】:

  • @haim770 非常感谢。这解决了问题。谢谢一百万
  • 也谢谢你。我无法在之前的评论中输入你的名字。
  • 我添加了一项无法正常工作的附加功能。我想以表格形式显示可供出售的 StoreProducts,并允许用户输入每件商品的销售数量。它应该更新“TotalAmount”(价格*售出的单位),并提供所有售出产品的总数。这里是JSFIDDLE。非常感谢。
  • 用于设置其他值的ko.computed 不应返回新值。你不应该替换SoldGasInventories,而是像我上面那样使用另一个名字。 (实际上,您甚至不需要给它命名。)但解决方法是使用value 绑定&lt;input&gt;jsfiddle.net/8nj31seh/55
  • 非常感谢您的解释。我知道了。一个问题。在让我们留在商店部分的当前功能中。当我在输入框中输入一个值并从该输入框中失去焦点时,即计算函数运行并计算值。如果我希望它在我输入一个值后立即运行(不离开输入框),我需要做什么。我希望我已经解释过了。非常感谢朋友。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-11
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 2012-04-20
  • 2017-09-02
相关资源
最近更新 更多