Knockout计算使用上次迭代中的变量在循环中创建

时间:2016-02-26 16:31:08

标签: javascript knockout.js

如何在循环中创建ko.computed变量,以便在重新计算时,计算函数内部循环变量的值与首次定义计算函数时的变量相同?

这是我期望闭包工作的方式,但是:

http://jsbin.com/dileju/6/edit?html,js,output (在输入框中输入1以外的数字,然后按返回)

重新计算时使用的值是循环最后一次迭代中变量的值。

2 个答案:

答案 0 :(得分:1)

摆脱for循环,它搞乱了(因为关闭的方式如同@Andrew在评论中正确指出的那样)。

var ViewModel = function() {
  var self = this;
  self.multipler = ko.observable(1);
  self.things = ko.observableArray();

  self.fakeServerData = [
    { id: 1, properties: { name: '1', val: 1 }},
    { id: 2, properties: { name: '2', val: 2 }},
    { id: 3, properties: { name: '3', val: 3 }}
  ];

  ko.utils.arrayForEach(self.fakeServerData, function (item) {
    var props = item.properties,
        multi = +self.multipler();

    props.computed = ko.pureComputed(function () {
      return multi * props.val;
    });
  });
};

ko.applyBindings(new ViewModel());

经验法则是:Don't make functions in a loop。如果必须创建函数,请不要使用循环。

避免循环的方法是使用本机数组函数(Array.prototype.forEach)或来自各种库的等价函数,例如knockout自己的ko.utils.arrayForEach(),jQuery' s {{ 1}}或下划线/ lodash' s $.each和其他人。

答案 1 :(得分:1)

对于你正在做的事情,你并不需要为数组中的每个元素计算。您可以使用函数并将其传递给当前元素。函数在绑定中工作正常。 Knockout将跟踪其可观察的依赖关系。

所以你的绑定将是

<span data-bind="text: $parent.thingy($data)"></span>

该功能将是:

self.thingy = function (data) {
  var mult = parseInt(self.multipler());
  return mult * data.val;
};

你可以建立你的东西列表,如:

for (var i = 0; i < self.fakeServerData.length; i++) {
  var props = self.fakeServerData[i].properties;
  self.things.push(props);
}