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

如果您从创建一个空的 viewModel... 开始,它的构造函数不接受任何参数,如下所示:

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 上的相同属性。只需在您的 plainJsObject 中使用新值再次调用相同的东西:

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

由于您(我假设)已经在代码中的某个位置执行了 ko.applyBindings(),因此上面的这一行将立即更新您的视图。

于 2013-02-27T19:42:50.990 回答
0

您应该只需要执行一次绑定,因此只需将其保留在任何事件驱动的函数调用之外。

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

我认为您在上面的示例中过于复杂了您的代码。我只返回一组 Product 对象,其中包含描述、单价、数量等属性,然后计算总数,使用 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 回答