3

ノックアウトとマッピング プラグインを使用して小さなウィジェットを更新しようとしています。これまでの私のコードは次のとおりです。

var AppViewModel = function (data, total, qty) {
    var self = this;
    self.Products = ko.mapping.fromJS(data, {}, this);
    self.CartTotals = ko.observable(total);
    self.TotalQty = ko.observable(qty);
};

var func = function(u) {
    return $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", data: "{}", dataType: "json", url: u });
},
getQtyTotal = function(b) {
    var a = 0;
    $.each(b.Table.Rows, function(c) {
        a += parseInt(b.Table.Rows[c].Quantity) || 0;
    });
    return a;
};

$.when(func("/store/MiniCart.aspx/GetShoppingCartInfo"), func("/store/MiniCart.aspx/GetCartTotal")).done(function (jsonA, jsonB) {
    var ds = $.parseJSON(jsonA[0].d), ds2 = $.parseJSON(jsonB[0].d), qtyTotal = getQtyTotal(ds);
    ko.applyBindings(new AppViewModel(ds, ds2, qtyTotal));
});

<div class="cartDropDownProductItemWrapper" data-bind="foreach: Products.Table.Rows">
    <div class="cartDropDownProductItem">
        <div class="cartDropDownProductImg">
            <img id="cart_details_rpt_prod_image_0" style="height: 71px; width: 55px;" data-bind="attr: { src: ProductImageURL }">
        </div>

        <div class="cartDropDownProductDesc">
            <h6><a data-bind="text: ModelName, attr: { href: ProductLink }"></a></h6>
            <div class="cartDropDownProductDescInner">
            <div class="cartDropDownColor"> COLOR 
                <strong><span data-bind="text:ColorName"></span></strong>
            </div>
            <div class="cartDropDownSize"> SIZE
                <strong><span data-bind="text: SizeName"></span></strong>
            </div>
            <div class="cartDropDownSize"> QTY 
                <strong><span data-bind="text: Quantity"></span></strong>
            </div>
            <div class="cartDropDownPrice"> PRICE 
                <strong><span data-bind="text: UnitCost().toFixed(2)"></span></strong>
            </div>
            <div class="cartDropDownRemove">
                <a href="javascript:void(0);" class="remove" onclick="removeItem('v3BuhngpE4c=')">
                    <img src="/images/layout/icons/remove.gif" alt="Remove Item">
                </a>
            </div>
        </div>
    </div>
    <div class="clear"></div>
</div>


<!-- end fo reach -->
<div class="clear"></div>
<div class="cartDropDownButtons clearfix">
    <ul class="clearfix">
        <li class="countItems"><span data-bind="text: TotalQty"></span> Items</li>
        <li class="subTotal" id="subTotal">SUBTOTAL: $<span data-bind="text: CartTotals().toFixed(2)"></span></li>
    </ul>
</div>

最初は正常にレンダリングされますが、jQuery クリック イベントで再バインドして呼び出しようとすると、次のようになります。

   ko.applyBindings(new AppViewModel(ds, ds2, qtyTotal));

データを複製します。

4

2 に答える 2

2

次のように、コンストラクターを介して引数を取らない空のビューモデルを作成することから始めると、次のようになります。

function ViewModel()
{
    var self = this;
}
var viewModel = new ViewModel();

...次に、ko.mapping を使用してデータをロードするために名前で参照できます。次のようにします。

ko.mapping.fromJS({ "PropertyName": plainJsObject }, {}, viewModel);

これが行うことは、 plainJsObject でko.mapping マジックを実行し、結果を viewModel オブジェクトのプロパティ (この場合は PropertyName と呼ばれる) に入れることです。

あなたが特に気にする部分はこれです:

サーバーからの新しいデータでviewModel.PropertyNameにあるデータを更新したい場合...まったく同じメソッドを呼び出すだけで、viewModelの同じプロパティが更新されます。単純な JsObject に新しい値を指定して、これと同じことをもう一度呼び出すだけです。

ko.mapping.fromJS({ "PropertyName": plainJsObject }, {}, viewModel);

コードのある時点で既に ko.applyBindings() を実行しているので (私は推測します)、上記のこの行はすぐにビューを更新します。

于 2013-02-27T19:42:50.990 に答える
0

バインディングは 1 回だけ実行する必要があるため、イベント ドリブンの関数呼び出しの外側に置いてください。

 ko.applyBindings(new AppViewModel(ds, ds2, qtyTotal));

上記の例では、コードを複雑にしすぎていると思います。説明、単価、数量などのプロパティを含む製品オブジェクトのセットを返し、合計を計算するには、ユーザーが数量を増減しようとすると自動的に更新される ko 計算変数を使用します。

function Product(item) {
    var self = this;
    self.description = ko.observable(item.description);
    self.quantity = ko.observable(item.quantity);
    self.unitPrice = ko.observable(item.unitPrice);
    self.total =  ko.computed(function() {
        return self.quantity() * self.unitPrice();
    });
}

function AppViewModel() {
    var self = this;
    self.products = ko.observableArray([]);
    self.overvallTotal =  ko.computed(function() {
        var total = 0;
        for (var i = 0; i < self.products().length; i++) {
            total += self.products()[i].total;
        }
        return total;
    });        
    self.removeProduct = function(item) { self.products.remove(item) };

    // Load initial state from server, convert it to Product instances
    $.getJSON("/store/MiniCart.aspx/GetShoppingCartInfo", function(allData) {
        var mappedProducts = $.map(allData, function(item) { return new Product(item) });
        self.products(mappedProducts);
    });    
}

ko.applyBindings(new AppViewModel());

これを処理するには、サーバー側の json の結果を調整する必要があります。

于 2013-01-06T19:16:32.520 に答える