我正在开发一个项目,要求我使用Kendo UI和Knockout.js作为移动应用程序,作为一种绑定这些库的方法我正在使用knockout-kendo库,该应用程序包含一个简单的产品列表每个产品和购物车的详细视图,但是我在更新购物车中的商品数量时遇到了一些问题.
我在我的应用程序中使用knockout-kendo绑定如下:
<div data-role="view" id="cart" data-title="Cart" data-layout="main-layout"> <div data-bind="if: items().length == 0">No items currently in cart</div> <ul data-role="listview" data-style="inset" data-bind="kendoListView: { data: items,template: cartTemplate }"></ul> </div>
模板的位置是:
<script type="text/x-kendo-template" id="cartListTemplate"> <div class="km-listview-link cart-item-container" data-id="#= Id #"> <div class="product-image"> <img src="#= ImageUrl #"> </div> <div class="product-description"> <p>#= Name #</p> <p>#= formattedPrice #</p> <p>#= quantity #</p> </div> <a data-role="button" data-icon="delete" class="km-primary" data-bind="click: removeItem">Delete</a> </div> </script>
而viewmodel是:
Cartviewmodel : function () { var self = this; globalKo.cartItems = self.items = ko.observableArray(JSON.parse(localStorage.getItem('cart')) || []); self.cartTemplate = kendo.template($('#cartListTemplate').html()); self.removeItem = function (vm,event) { var element = $(event.target).parents('div.cart-item-container'); productId = element.data('id'); var cartItem = globalKo.cartItems().filter(function (element) { return element.Id == productId; })[0]; if (cartItem.quantity > 1) { cartItem.quantity --; } else { self.items.remove(cartItem); } app.saveCart(); self.items.valueHasMutated(); } }
它显然按预期工作,除了当数组值变异(值hasHasMutated函数被调用或数组有一个元素添加或删除)突然按钮停止按钮并变成简单文本,它们也不起作用停止调用他们绑定的函数.从代码片段中可以看出,单击绑定是通过标记完成的,并且不能按预期工作.
值得注意的是,我正在调用valueHasMutated函数,否则视图不会更新购物车中的商品数量.
为了说明这里的问题是一些图像:
在按下按钮之前
按下按钮后
我不太明白为什么会发生这种情况,我猜它与Kendo UI有关,而不是与knockout.js有关.
我也做了一个演示问题的小提琴,你可以找到它here
解决方法
正如本文所指出的那样,没有完全支持Kendo和Knockout集成(
http://www.telerik.com/blogs/knockout-js-and-kendo-ui—a-potent-duo),因此在某些情况下必须完成一些工作.
首先尝试使用Knockout模板:
<script type="text/html" id="cartListTemplate"> <div class="km-listview-link cart-item-container" data-id="text: Id"> <div class="product-image"> <img data-bind="attr:{src: ImageUrl}"> </div> <div class="product-description"> <p data-bind="text: Name"></p> <p data-bind="text: formattedPrice"></p> <p data-bind="text: quantity"></p> </div> <button data-icon="delete" class="km-big" data-bind="kendoMobileButton: $root.removeItem">Delete</button> </div> </script>
请注意,’a’标记已更改为简单的按钮标记,将其绑定到kendo移动按钮(https://rniemeyer.github.io/knockout-kendo/web/Button.html).然后必须通知视图使用Knockout模板而不是Kendo模板:
<div data-role="view" id="cart" data-title="Cart" data-layout="main-layout"> <div data-bind="if: items().length == 0">No items currently in cart</div> <ul data-role="listview" data-style="inset" data-bind="kendoListView: { data: items,template: 'cartListTemplate',useKOTemplates: true }"></ul> </div>
最后,为了使删除功能正常工作,将其绑定到视图模型并接收当前项作为参数:
self.removeItem = function(item) { if (item.quantity > 1) { var cartItem = self.items().filter(function(element) { return element.Id == item.Id; })[0]; cartItem.quantity--; self.items.valueHasMutated(); } else { self.items.remove(item); } app.saveCart(); }.bind(self);
唯一需要注意的是,值已经变异,视图刷新有时会弄乱Kendo小部件,因此kendo knockout库使用指定data-bind属性中的角色的普通标记.
这是因为目前淘汰的kendo库不支持数据角色初始化,而是使用数据绑定初始化.