我有以下JavaScript数组,
[{"unitPrice": 2499,"currency":"$","productId":1,"retailerId":1,"productName":"XX ","formattedPrice":"$ 2,499","productImage":"Images/2012_08_12_00_45_39_4539.jpg","productQuantity":"9","totalPrice":19992},
{"unitPrice": 4999,"currency":"$","productId":2,"retailerId":1,"productName":"XX","formattedPrice":"$ 4,999","productImage":"Images/2012_08_12_00_46_45_4645.jpg","productQuantity":2,"totalPrice":9998},
{"unitPrice":4555,"currency":"$","productId":1,"retailerId":1,"productName":"XXXXX","formattedPrice":"$ 4,555","productImage":"Images/2013_02_12_10_57_49_5749_9868.png","productQuantity":3,"totalPrice":13665}]
这是相关的html,
<table>
<tbody data-bind="foreach: $root">
<tr>
<td><img width="45" height="45" alt="" data-bind="attr:{src: productImage}"/></td>
<td><span data-bind="html: productName"></span></td>
<td><span data-bind="html: formattedPrice"></span></td>
<td><input type="number" class="quantity" data-bind="value: productQuantity, attr:{'data-id': productId }" /></td>
<td><span data-bind="html: totalPrice"></span></td>
</tr>
</tbody>
</table>
然后我创建了可观察数组,
observableItems = ko.observableArray(items);
ko.applyBindings(observableItems);
现在我能够使用
获得一个特定元素 var obj = ko.utils.arrayFirst(list(), function (item) {
return item.productId === id;
});
然而,当我改变时,
item.productQuantity = 20;
但是UI没有更新。也试过,
item.productQuantity(item.productQuantity)
但是获取错误productQuantity不是一个函数
答案 0 :(得分:17)
上述行为是因为只有数组是可观察的,而不是数组中的单个元素或每个元素的属性。
执行item.productQuantity = 20;
时,这将更新属性,但由于它不是可观察的,因此UI不会更新。
类似地,item.productQuantity(20)
会给您一个错误,因为productQuantity
不是可观察的。
您应该查看为数组的每个元素定义对象结构,然后将该类型的元素添加到您的可观察数组中。完成此操作后,您将能够执行item.productQuantity(20)
之类的操作,UI将立即更新。
编辑添加了OP :)提供的功能。此函数将数组中元素的每个属性转换为可观察对象。
function convertToObservable(list)
{
var newList = [];
$.each(list, function (i, obj) {
var newObj = {};
Object.keys(obj).forEach(function (key) {
newObj[key] = ko.observable(obj[key]);
});
newList.push(newObj);
});
return newList;
}
结束编辑
如果您无法更改该段代码,您还可以执行observableItems.valueHasMutated()
之类的操作。但是,这不是一件好事,因为它向KO和您的UI发出信号表明整个数组已经更改,UI将根据绑定呈现整个数组。
答案 1 :(得分:10)
您可以轻松使用ko.mapping插件将对象转换为可观察对象:http://knockoutjs.com/documentation/plugins-mapping.html
将常规JS实体转换为可观察实体:
var viewModel = ko.mapping.fromJS(data);
将observable对象转换为常规JS对象:
var unmapped = ko.mapping.toJS(viewModel);