10

私は次の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を取得することは関数ではありません

4

2 に答える 2

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がバインディングに基づいて配列全体をレンダリングするため、適切な方法ではありません。

于 2013-02-19T08:53:35.900 に答える
11

ko.mappingプラグインを使用して、オブジェクトを簡単に観察可能に変換できます:http: //knockoutjs.com/documentation/plugins-mapping.html

通常のJSエンティティを監視可能なエンティティに変換します。

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

監視可能なオブジェクトを通常のJSオブジェクトに変換します。

var unmapped = ko.mapping.toJS(viewModel);
于 2013-02-19T10:24:25.797 に答える