【问题标题】:Knockout-Kendo listview not initializing after valueHasMutatedKnockout-Kendo listview 在 valueHasMutated 之后未初始化
【发布时间】:2016-04-13 20:19:03
【问题描述】:

我正在开发一个项目,该项目要求我将 Kendo UI 和 Knockout.js 一起用于移动应用程序,作为绑定此库的一种方式我使用的是 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 函数被调用或数组添加或删除了一个元素)突然按钮不再是按钮并变成简单的文本,它们也不会'不起作用,因为他们停止调用他们绑定的函数。从代码 sn-ps 可以看出,点击绑定是通过标记完成的,不能按预期工作。

值得注意的是,我正在调用 valueHasMutated 函数,否则视图不会更新购物车中的商品数量。

为了说明问题,这里有一些图像:

按下按钮之前

按下按钮后

我不太明白为什么会发生这种情况,我猜它与 Kendo UI 有关,而与 knockout.js 无关。

我也做了一个fiddle来演示这个问题,你可以找到它here

【问题讨论】:

    标签: knockout.js kendo-ui knockout-kendo


    【解决方案1】:

    正如本文指出的那样,没有完全支持 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”标签已更改为将其绑定到剑道移动按钮 (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>
    

    最后,为了让delete功能正常工作,将其绑定到视图模型并接收当前项作为参数:

    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 淘汰库使用在 data-bind 属性中指定角色的普通标签。 这是因为目前淘汰的剑道库不支持数据角色初始化,而是使用数据绑定初始化。

    请在以下位置找到工作示例:https://jsfiddle.net/aveze/Lykducos/

    【讨论】:

      【解决方案2】:

      您可以尝试使用knockout templatesknockout-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)
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多