【问题标题】:Conditionally removing root level and nested observableArrays in Knockout.js有条件地删除 Knockout.js 中的根级别和嵌套的 observableArrays
【发布时间】:2012-08-19 14:02:14
【问题描述】:

jsFiddle:http://jsfiddle.net/brandondurham/g3exx/

我正在设置购物车并在我的模型中使用以下 JSON 数据:

{
    "cartItems" : [
        {
            "itemName" : "Product 1",
            "itemDesc" : "One year subscription through 14 November 2013",
            "itemType" : "subscription",
            "itemPrice" : 299,
            "itemFreebies" : false
        }, {
            "itemName" : "Product 2",
            "itemDesc" : "OpenType format",
            "itemType" : "desktop",
            "itemPrice" : 4499,
            "itemFreebies" : [{
                "freebieName" : "Product 2-a",
                "freebieDesc" : "included with your workstation license",
                "freebieOriginalPrice" : 99
            }]
        }, {
            "itemName" : "Product 3",
            "itemDesc" : "OpenType format",
            "itemType" : "desktop",
            "itemPrice" : 8999,
            "itemFreebies" : [{
                "freebieName" : "Product 3-a",
                "freebieDesc" : "included with your workstation license",
                "freebieOriginalPrice" : 99
            }]
        }, {
            "itemName" : "Product 4",
            "itemDesc" : "OpenType format",
            "itemType" : "desktop",
            "itemPrice" : 99,
            "itemFreebies" : [{
                "freebieName" : "Product 4-a",
                "freebieDesc" : "included with your workstation license",
                "freebieOriginalPrice" : 99
            }]
        }, {
            "itemName" : "Product 5",
            "itemDesc" : "",
            "itemType" : "webfont",
            "itemPrice" : 49,
            "itemFreebies" : false
        }, {
            "itemName" : "Product 6",
            "itemDesc" : "for use with Cloud.typography",
            "itemType" : "webfont",
            "itemPrice" : 99,
            "itemFreebies" : false
        }
    ]
}

购物车中某些类型的商品之间存在一些关系。例如,此 JSON 中的第一项是 itemType“订阅”。当用户在他们的购物车中有订阅时,他们会得到一些免费的东西,这取决于他们的购物车中还有什么(因此在某些项目中嵌套了 itemFreebies 数组)。他们还可以添加与此订阅相关的某些类型的项目(即“webfonts”)。因此,当用户从他们的购物车中删除订阅时,所有这些免费项目和网络字体也必须被删除。这是我目前用来执行此操作的函数:

removeRelatives: function (itemType) {
    var siblings = CartModel.cartItems();
    switch (itemType) {
        case "subscription":
            CartModel.cartItems.remove(function(item) { return item.itemType() == "webfont" });
            $.each(CartModel.cartItems(), function(index, sib) {
                if (sib.itemFreebies) {
                    sib.itemFreebies.removeAll();
                }
            });
        break;
    }
}

此行删除任何与“webfont”`itemType: 匹配的根级别项目:

CartModel.cartItems.remove(function(item) { return item.itemType() == "webfont" });

第二位循环遍历所有cartItems 并搜索不为假的itemFreebies 节点并将其删除:

$.each(CartModel.cartItems(), function(index, sib) {
    if (sib.itemFreebies) {
        sib.itemFreebies.removeAll();
    }
});

这是我不确定的第二点。它正在工作,但我怀疑这不是最干净的方法。此外,我为那些嵌套的itemFreebies 设置的beforeRemove 动画不起作用。删除时,它们会从屏幕上消失。

这是 HTML 方面的内容:

<ul id="cart-contents" data-bind="template: { name: 'cart-item-template', foreach: cartItems, beforeRemove: CartPackage.beforeRemove }">
    </ul>
<div id="running-totals">
    <div class="totals" data-bind="visible: cartItems().length > 0">
        <div><strong>Subtotal</strong></div>
        <div><span class="denomination">USD</span>  <strong id="subtotal"><span data-bind="formatUSD: CartPackage.totalSurcharge()"></span></strong></div>
    </div>
    <div class="empty-cart">There are currently no items in your shopping cart.</div>
</div>
<div class="call-to-action" data-bind="visible: cartItems().length > 0">
    <div class="split">
        <div class="messages">&nbsp;</div>
        <div class="actions">
            <button class="cancel">Continue Shopping</button>
            <button class="action">Checkout</button>
        </div>
    </div>
</div>
<input type="hidden" value="" data-bind="value: cartItems().length">
<script type="text/html" id="cart-item-template">
    <li>
        <button class="delete-item">Delete</button>
        <ul>
            <li data-bind="attr: {'class': itemType}">
                <div class="details">
                    <h5><strong data-bind="text: itemName">Product Name</strong><!-- ko if: itemType() === 'desktop' --> Desktop fonts<!-- /ko --><!-- ko if: itemType() === 'webfont' --> Webfonts<!-- /ko --></h5>
                    <p data-bind="text: itemDesc">One year subscription through 14 November 2013</p>
                </div>
                <div class="quantity">
                    <!-- ko if: itemType() === "subscription" --><select data-bind='options: SubscriptionData, optionsText: "name", optionsValue: "price", value: itemPrice'></select><!-- /ko -->
                    <!-- ko if: itemType() === "desktop" || itemType() === "webfont" --><select data-bind='options: DesktopData, optionsText: "name", optionsValue: "price", value: itemPrice'></select><!-- /ko -->
                </div>
                <div class="cost" data-bind="formatUSD: itemPrice">$ 0</div>
            </li>
            <!-- ko if: itemFreebies -->
            <!-- ko foreach: itemFreebies, beforeRemove: CartPackage.beforeRemove -->
            <li class="webfont">
                <div class="details">
                    <h5><strong data-bind="text: freebieName">Product</strong> Webfonts</h5>
                    <p data-bind="text: freebieDesc">Included with your workstation license</p>
                </div>
                <div class="quantity">&nbsp;</div>
                <div class="cost">
                    <span class="original-price" data-bind="formatUSD: freebieOriginalPrice">$ 49.00</span>  <span class="free">FREE!</span>
                </div>
            </li>
            <!-- /ko -->
            <!-- /ko -->
        </ul>
    </li>
</script>

关于为什么我的beforeRemove 不起作用的建议?实现我想要做的更清洁的方式?

谢谢!如果您需要查看更多代码,请告诉我...

【问题讨论】:

  • 对于你的beforeMove 语法,你需要像ko foreach: { data: itemFreebies, beforeRemove: CartPackage.beforeRemove } 那样做,否则它只是一个beforeRemove 顶级绑定,除非它们是具有该名称的自定义绑定,否则它会被忽略。

标签: javascript arrays knockout.js knockout-mapping-plugin


【解决方案1】:

对于beforeRemove 动画,看起来这只是我在上面评论中列出的语法问题。

据我现在所知,似乎工作正常:http://jsfiddle.net/rniemeyer/g3exx/3/

对于去掉freebies的代码,可以简化为:

$.each(CartModel.cartItems(), function(index, sib) {
    sib.itemFreebies([]);
});

对于关系部分,我认为没有一种简单的方法可以比您现在所做的更好地对其进行建模。一种想法是在你的根视图模型上创建计算的 observables,代表任何整体概念,如hasSubscription。然后,每个购物车项目都可以订阅 hasSubscription 并删除他们自己的免费赠品,如果该值发生变化。它至少会在订阅购物车项目和其他购物车项目之间添加一些间接性。但是,它会增加您必须映射项目的方式的复杂性。

如果您想寻求类似的选择,我很乐意提供进一步的帮助。

【讨论】:

  • 谢谢!任何想法为什么动画在删除时对免费赠品不起作用?
  • 当您放慢速度时,似乎免费赠品正在发挥作用。您期待不同的效果吗?
猜你喜欢
  • 2014-02-25
  • 1970-01-01
  • 1970-01-01
  • 2021-07-15
  • 1970-01-01
  • 2020-07-24
  • 2020-10-02
  • 2018-09-15
  • 2021-12-23
相关资源
最近更新 更多