我有以下 View 模型:
var myViewModel = {
categories: ko.observableArray([
{ name: ko.observable('Fruit'),
items: ko.observableArray([
ko.observable('Apple'),
ko.observable('Orange'),
ko.observable('Banana'),
]),
},
]),
};
我想为这个数组的每一项添加一个计算值:
$.each(myViewModel.categories(), function(index, cat){
cat.num = ko.computed(function(){
return cat.items().length;
}, cat);
});
这是我的 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>
而且效果很好!这是结果:
Fruit: Apple
Fruit: Orange
Fruit: Banana
3
但现在假设我的数据发生了变化,我需要反射(reflect)这些变化:
myViewModel.categories([
{
name: "Fruit",
items: ["Apple", "Banana"],
},
{
name: "Veg",
items: ["Potato", "Carridge"],
}
]);
它不起作用 - 我没有在每个列表的末尾看到 num
。你能帮我解决这个问题吗?这是 codepen
最佳答案
当然这是行不通的,因为你正在替换 observableArray
的全部内容。你的这段代码:
$.each(myViewModel.categories(), function(index, cat){
cat.num = ko.computed(function(){
return cat.items().length;
}, cat);
});
将 num
属性添加到调用时数组中存在的项目。通过执行以下操作为您的 observableArray
提供一个新的支持数组:
myViewModel.categories([
{
name: "Fruit",
items: ["Apple", "Banana"],
},
{
name: "Veg",
items: ["Potato", "Carridge"],
}
])
当然,您丢失了旧数组,因此丢失了在项目上定义的计算可观察值,而不是可观察数组。 Knockout 当然无法知道它应该如何以及是否应该将计算属性添加到新数组中的每个项目。
解决方法:
当您替换 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);
});
或者更好的是,您可以使用已定义的属性实例化数组中的对象。注意:您不必为每个项目一遍又一遍地编写函数,例如,您可以为数组项目定义一个构造函数:
function Category(name, items) {
var self = this;
this.name = name;
this.items = ko.observableArray(items);
this.num = ko.computed(function() {
return self.items().length;
});
};
然后,这就是你如何创建一个新的:
var newItem = new Category('Category 1', [ 'Apple', 'Banana']);
并将其插入可观察数组:
myViewModel.categories.push(newItem);
这会添加一个项目并保留现有的项目,或者像您所做的那样,您可以这样提供一个全新的数组:
myViewModel.categories([
new Category('Fruit', ['Apple', 'Banana' ]),
new Category('Veg', ['Potato', 'Carridge' ])
]);
关于javascript - 可观察数组的 knockout 计算项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41952307/