Javascript 如何更新knockoutjs中的可观察数组元素?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14953248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to update observable array element in knockoutjs?
提问by user960567
I have following JavaScript array,
我有以下 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}]
here is the relevent html,
这是相关的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>
Then I have created observable array as,
然后我创建了可观察的数组,
observableItems = ko.observableArray(items);
ko.applyBindings(observableItems);
Now I was able to get an specfic element using,
现在我能够得到一个特定的元素,
var obj = ko.utils.arrayFirst(list(), function (item) {
return item.productId === id;
});
However when I change,
然而当我改变时,
item.productQuantity = 20;
But UI is not updating. Tried also,
但是用户界面没有更新。也试过,
item.productQuantity(item.productQuantity)
But getting error productQuantity is not a function
但是得到错误 productQuantity 不是一个函数
回答by ryadavilli
The above behavior is because only the array is an observable and not the individual elements within the array or the properties of each element.
上述行为是因为只有数组是可观察的,而不是数组中的单个元素或每个元素的属性。
When you do item.productQuantity = 20;, this will update the property but since it is not an observable, the UI does not get updated.
当您这样做时item.productQuantity = 20;,这将更新属性,但由于它不是可观察的,因此 UI 不会更新。
Similary, item.productQuantity(20)gives you an error because productQuantityis not an observable.
类似地,item.productQuantity(20)给你一个错误,因为productQuantity它不是一个可观察的。
You should look at defining the object structure for each element of your array and then add elements of that type to your observable array. Once this is done, you will be able to do something like item.productQuantity(20)and the UI will update itself immediately.
您应该查看为数组的每个元素定义对象结构,然后将该类型的元素添加到可观察数组中。完成此操作后,您将能够执行类似操作item.productQuantity(20),并且 UI 将立即自行更新。
EDITAdded the function provided by the OP :). This function will convert each property of the elements in an array to observables.
编辑添加了 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;
}
END EDIT
结束编辑
If you are unable to change that piece of code, you can also do something like observableItems.valueHasMutated(). However, this is not a good thing to do as it signals to KO and your UI that the whole array has changed and the UI will render the whole array based on the bindings.
如果您无法更改那段代码,您还可以执行类似observableItems.valueHasMutated(). 但是,这不是一件好事,因为它会向 KO 和您的 UI 发出信号,表明整个数组已更改,并且 UI 将根据绑定呈现整个数组。
回答by Anh Bui
You can easily use ko.mapping plugin to convert object to become observable: http://knockoutjs.com/documentation/plugins-mapping.html
您可以轻松使用 ko.mapping 插件将对象转换为可观察对象:http://knockoutjs.com/documentation/plugins-mapping.html
Convert regular JS entity to observable entity:
将常规 JS 实体转换为可观察实体:
var viewModel = ko.mapping.fromJS(data);
Convert observable object to regular JS object:
将 observable 对象转换为常规 JS 对象:
var unmapped = ko.mapping.toJS(viewModel);

