简体   繁体   English

Knockout计算可观察数组的项目

[英]Knockout computed items of observable array

I have the following ViewModel: 我有以下ViewModel:

var myViewModel = {
  categories: ko.observableArray([
    { name: ko.observable('Fruit'), 
      items: ko.observableArray([ 
        ko.observable('Apple'),
        ko.observable('Orange'), 
        ko.observable('Banana'), 
      ]),
    },
  ]),
};

I want to add a computed value for each item of this array: 我想为这个数组的每个项添加一个计算值:

$.each(myViewModel.categories(), function(index, cat){
  cat.num = ko.computed(function(){
    return cat.items().length;
  }, cat);
});

This is my HTML: 这是我的HTML:

<ul data-bind="foreach: { data: categories, as: 'category' }">
    <li>
        <ul data-bind="foreach: { data: items, as: 'item' }">
            <li>
                <span data-bind="text: category.name"></span>:
                <span data-bind="text: item"></span>
            </li> 
        </ul>
      <span data-bind="text: category.num"></span>
    </li>
</ul>

And it works just great! 它的效果非常好! Here is the result: 结果如下:

Fruit: Apple
Fruit: Orange
Fruit: Banana
3

But now let's say my data has changed and I need to reflect those changes: 但现在让我们说我的数据发生了变化,我需要反映这些变化:

myViewModel.categories([
  {
    name: "Fruit",
    items: ["Apple", "Banana"],
  },
  {
    name: "Veg",
    items: ["Potato", "Carridge"],
  }
]);

And it doesn't work - I don't see num at the end of each list. 它不起作用 - 我没有在每个列表的末尾看到num Could you please help me to fix this? 你能帮我解决这个问题吗? Here is the codepen 这是codepen

Of course it does not work, because you are replacing the entire content of the observableArray . 当然它不起作用,因为你要替换observableArray的整个内容。 This code of yours: 你的这个代码:

$.each(myViewModel.categories(), function(index, cat){
    cat.num = ko.computed(function(){
        return cat.items().length;
    }, cat);
});

adds the num property to the items that exist in the array at the time of the call. num属性添加到调用时数组中存在的项目。 By giving a new backing array to your observableArray by doing this: 通过执行以下操作,为您的observableArray提供一个新的后备数组:

myViewModel.categories([
  {
    name: "Fruit",
    items: ["Apple", "Banana"],
  },
  {
    name: "Veg",
    items: ["Potato", "Carridge"],
  }
])

you, of course, lose the old array and thus the computed observables which are defined on the items and not the observable array. 当然,你丢失旧的数组,从而丢失了在项目而不是可观察数组上定义的计算的observable。 Knockout of course has no way to know how and whether it should add the computed property to every item in the new array. Knockout当然无法知道如何以及是否应该将计算属性添加到新数组中的每个项目。

Solution: 解:

You can either do the same property addition when you replace the backing array of your observableArray like this: 当您替换observableArray的后备数组时,您可以执行相同的属性添加,如下所示:

myViewModel.categories([
  {
    name: "Fruit",
    items: ["Apple", "Banana"],
  },
  {
    name: "Veg",
    items: ["Potato", "Carridge"],
  }
]);
$.each(myViewModel.categories(), function(index, cat){
    cat.num = ko.computed(function(){
        return cat.items().length;
    }, cat);
});

or better yet, you could instantiate the objects in the array with the property already defined. 或者更好的是,您可以使用已定义的属性实例化数组中的对象。 Note: you don't have to write the function over and over again for each item, you could, for instance, define a constructor for the array items: 注意:您不必为每个项目反复编写函数,例如,您可以为数组项定义构造函数:

function Category(name, items) {
  var self = this;

  this.name = name;
  this.items = ko.observableArray(items);
  this.num = ko.computed(function() {
    return self.items().length;
  });
};

and then, this is how you create a new one: 然后,这就是你创建一个新的方法:

var newItem = new Category('Category 1', [ 'Apple', 'Banana']);

and insert it into the observable array: 并将其插入可观察数组:

myViewModel.categories.push(newItem);

this adds one item and keeps the existing ones, or, as you did, you could supply a whole new array as so: 这会添加一个项目并保留现有项目,或者,如您所做的那样,您可以提供一个全新的数组:

myViewModel.categories([
  new Category('Fruit', ['Apple', 'Banana' ]),
  new Category('Veg', ['Potato', 'Carridge' ])
]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM