2013-02-19 89 views
10

我有以下的JavaScript阵列,如何更新knockoutjs中的可观察数组元素?

[{"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) 

但是,得到误差产品数量不是一个函数

回答

17

上述行为是因为只有阵列是可观察到的,而不是阵列中的各个元件或每个元件的特性。

当你做item.productQuantity = 20;,这将更新属性,但由于它不是一个可观察的,UI不会被更新。

相似,item.productQuantity(20)给你一个错误,因为productQuantity是不可观察的。

您应该看看为数组中的每个元素定义对象结构,然后将该类型的元素添加到可观察数组中。完成此操作后,您将可以执行诸如item.productQuantity(20)之类的操作,UI将立即自行更新。

编辑增加了由OP提供的功能:)。该函数将数组中元素的每个属性转换为observables。

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将根据绑定呈现整个数组。

+0

observableItems.valueHasMutated()不起作用 – user960567 2013-02-19 08:55:34

+0

通过添加此功能获得它, function conve rtToObservable(list){var_new_list = [];}} $。每个(列表,函数(i,obj))var newObj = {}; Object.keys(obj).forEach(function(key){newObj [key] = ko.observable(obj [key]); }); newList.push(newObj); }); return newList; } – user960567 2013-02-19 09:19:09

+0

请把这个里面的答案。 – user960567 2013-02-19 09:19:35

9

您可以轻松地使用ko.mapping插件转换对象变为可观察到的:http://knockoutjs.com/documentation/plugins-mapping.html

转换普通JS实体可观察到的实体:

var viewModel = ko.mapping.fromJS(data); 

转换可观察对象定期JS对象:

var unmapped = ko.mapping.toJS(viewModel); 
+0

OK,但如果观察到的阵列是许多对象的数组,如何你会更新一个对象的使用这种方法在阵列中的个人财产? – Andrew 2017-03-09 14:01:25

+0

你需要知道什么对象将阵列中进行更新,因此您将特定对象可观察到的,这是很好的性能明智的为好。 – 2017-03-12 15:09:15

相关问题