Knockout-Kendo listview 在 valueHasMutated 后未初始化
Knockout-Kendo listview not initializing after valueHasMutated
我正在开展一个项目,该项目要求我将 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();
}
}
这一切显然都按预期工作,除了当数组值发生变化(调用 valueHasMutated
函数或数组添加或删除元素)突然按钮不再是按钮并变成简单文本,它们也不起作用,因为它们停止调用它们绑定的函数。正如您从代码片段中看到的那样,点击绑定是通过标记完成的,并没有按预期工作。
值得注意的是,我正在调用 valueHasMutated
函数,否则视图不会更新购物车中的商品数量。
为了说明问题,这里有一些图片:
按下按钮之前
按下按钮后
我不太明白为什么会这样,我猜这与 Kendo UI 有关,与 knockout.js.[=19 关系不大=]
我也做了一个fiddle演示这个问题,你可以找到它here
你可以尝试使用 knockout templates and 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>
<div data-bind="if: items().length"><p data-bind="text: items().length"></p><p> items currently in the cart</p></div>
<ul data-role="listview" data-style="inset" data-bind="kendoListView: { data: items, template: 'cartListTemplate', useKOTemplates: true }"></ul>
</div>
创建命名模板
<script type="text/html" id="cartListTemplate">
<li class="km-listview-link cart-item-container" data-bind="attr: {'id': 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>
<a data-role="button" data-icon="delete" class="km-primary" data-bind="click: $root.removeItem">Delete</a>
</li>
通过拼接数组删除项目
this.removeItem = function (item) {
const deleteIndex = this.items.findIndex(i => i.Id === item.Id)
if (deleteIndex > -1) {
this.items.splice(deleteIndex, 1)
}
}.bind(this)
正如本文指出的那样,没有对 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 kendo 库不支持数据角色初始化,而是使用数据绑定初始化。
请在以下位置找到工作示例:https://jsfiddle.net/aveze/Lykducos/
我正在开展一个项目,该项目要求我将 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();
}
}
这一切显然都按预期工作,除了当数组值发生变化(调用 valueHasMutated
函数或数组添加或删除元素)突然按钮不再是按钮并变成简单文本,它们也不起作用,因为它们停止调用它们绑定的函数。正如您从代码片段中看到的那样,点击绑定是通过标记完成的,并没有按预期工作。
值得注意的是,我正在调用 valueHasMutated
函数,否则视图不会更新购物车中的商品数量。
为了说明问题,这里有一些图片:
按下按钮之前
按下按钮后
我不太明白为什么会这样,我猜这与 Kendo UI 有关,与 knockout.js.[=19 关系不大=]
我也做了一个fiddle演示这个问题,你可以找到它here
你可以尝试使用 knockout templates and 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> <div data-bind="if: items().length"><p data-bind="text: items().length"></p><p> items currently in the cart</p></div> <ul data-role="listview" data-style="inset" data-bind="kendoListView: { data: items, template: 'cartListTemplate', useKOTemplates: true }"></ul> </div>
创建命名模板
<script type="text/html" id="cartListTemplate"> <li class="km-listview-link cart-item-container" data-bind="attr: {'id': 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> <a data-role="button" data-icon="delete" class="km-primary" data-bind="click: $root.removeItem">Delete</a> </li>
通过拼接数组删除项目
this.removeItem = function (item) { const deleteIndex = this.items.findIndex(i => i.Id === item.Id) if (deleteIndex > -1) { this.items.splice(deleteIndex, 1) } }.bind(this)
正如本文指出的那样,没有对 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 kendo 库不支持数据角色初始化,而是使用数据绑定初始化。
请在以下位置找到工作示例:https://jsfiddle.net/aveze/Lykducos/