循环遍历数组以向每个对象添加ko.computed

时间:2015-09-19 05:29:59

标签: javascript knockout.js

我将来自服务器的viewmodel作为JSON传递,然后在调用ko.applyBindings()之前向viewmodel添加一些函数和observable。

我的问题是我想循环遍历一个对象数组,并在每个对象上添加一个计算的observable。但是,所有计算的observable似乎都绑定到我的数组中的最后一个对象。

这是循环:

for (var i = 0; i < viewModel.Records().length; i++)
{
    var record = viewModel.Records()[i];

    viewModel.Records()[i].CachedMonthlyAmount = ko.computed(function () {
        var frequencyType = viewModel.GetFrequencyTypeByID(record.SelectedFrequencyTypeID());
        return frequencyType.MonthlyCalculationFactor() * record.Amount();
    });
}

我还创建了this jsfiddle来演示。

2 个答案:

答案 0 :(得分:3)

在for循环中使用变量时,您需要创建closure(例如,使用立即调用的函数表达式 IIFE ),这样您就可以绑定record每个计算函数内的变量到计算函数之外的单独的不变量值。

只需要做:

for (var i = 0; i < viewModel.Records().length; i++)
{
    var record = viewModel.Records()[i];

    (function(record){
        record.CachedMonthlyAmount = ko.computed(function () {
            var frequencyType = viewModel.GetFrequencyTypeByID(record.SelectedFrequencyTypeID());
            return frequencyType.MonthlyCalculationFactor() * record.Amount();
        });
    }(record));
}

Js Fiddle Demo

答案 1 :(得分:2)

ko.computed的第二个参数定义了将用于计算计算回调函数中this的目标对象。因此,您可以将record作为第二个参数传递,这将导致正确的计算评估。

for (var i = 0; i < viewModel.Records().length; i++) {
    var record = viewModel.Records()[i];

    viewModel.Records()[i].CachedMonthlyAmount = ko.computed(function () {
        var frequencyType = viewModel.GetFrequencyTypeByID(this.SelectedFrequencyTypeID());
        return frequencyType.MonthlyCalculationFactor() * this.Amount();
    }, record);
}

ko.computed文档中了解有关managing this的详情。

更新了小提琴:http://jsfiddle.net/952pfm61/4/