我正在尝试使用knockout和映射插件刷新一个小部件。到目前为止,这是我的代码:
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 click事件并调用:
时 ko.applyBindings(new AppViewModel(ds, ds2, qtyTotal));
它复制了数据。
答案 0 :(得分:2)
如果你开始创建一个空的viewModel ...它不会通过它的构造函数获取参数,如下所示:
function ViewModel()
{
var self = this;
}
var viewModel = new ViewModel();
...然后您可以通过名称引用它来使用ko.mapping加载数据,如下所示:
ko.mapping.fromJS({ "PropertyName": plainJsObject }, {}, viewModel);
这样做是在plainJsObject上运行 ko.mapping magic ,并将结果填充到viewModel对象的属性(在本例中,称为PropertyName)。
您特别关注的部分是:
如果要使用服务器中的新数据刷新viewModel.PropertyName中的数据...您只需调用完全相同的方法,并在viewModel上更新相同的属性。只需在plainJsObject中使用新值再次调用同样的东西:
ko.mapping.fromJS({ "PropertyName": plainJsObject }, {}, viewModel);
由于您(我假设)已经在代码中的某个位置执行了ko.applyBindings(),因此上面的这一行会立即更新您的视图。
答案 1 :(得分: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结果才能使用此功能。