0

1. 目标

使用 JavaScript、KnockoutJS 或 jQuery 在列表中查找属性。

2. 场景

我有一个使用 KnockoutJS 来动态化其 UI 的商店应用程序。

3.问题

每个可添加到我商店购物车的产品都有一个添加按钮,但只有当产品不在购物车中时才可用。

我需要对购物车进行迭代,以发现我的可用产品列表中的每个产品是否已经在其中。

4.几段代码前...

我要添加到列表的可用产品的每个产品都使用此片段在按钮之间切换:

<!-- ko if: Summary.hasItem($element) -->
    <button class="btn btn-small action remove">
        <i class="icon-minus"></i>
    </button>
<!-- /ko -->
<!-- ko ifnot: Summary.hasItem($element) -->
    <button class="btn btn-small action add">
        <i class="icon-plus"></i>
    </button>
<!-- /ko -->

如您所见,我正在使用该hasItem()功能来检查产品是否已经在购物车中 - 但我必须实现它,我需要您的帮助才能做到这一点。

5. 我已经尝试过的

正如您在下面看到的,我尝试创建一个循环来逐个检查购物车中的产品,直到...

self.hasItem = function (element) {
    var $productId = $(element).closest("li").data("productid"),
        products = self.products();

    if (products.length > 0) {
        for (var product in products) {
            if (products[product].id() == $productId) {
                return true;
            } else {
                return false;
            }
        }
    }
};

... 出问题了!在下一章继续。

6. 出了问题

我的大脑无法计算逻辑,但是由于每个按钮都有这个循环,所以似乎一个运行时另一个不运行,或者如果列表中有一个项目,另一个不添加。

7.游乐场

玩这个!

8. 我要问...

我的循环/逻辑是对的吗?

4

3 回答 3

1

在您的情况下,这将起作用:

self.hasItem = function (element) {
    var $productId = $(element).closest("li").data("productid"),
        products = self.products();

     return ko.utils.arrayFirst(products, function(p){
         return (p.id() == $productId);               
     }) != null;
}

ko.utils.arrayFirst返回匹配给定谓词的第一项;否则为空。

于 2013-07-05T14:50:38.030 回答
1

您需要以不同的方式看待这一点,而不是调用“hasItem”,而应该在 Product 对象中包含类似“isSelected”的内容。

然后,您可以循环您的产品并说(伪代码)如果不是“isSelected”然后显示添加按钮。单击此添加按钮时,您的 Product 对象的“isSelected”属性将设置为 true。

尽可能让 Knockout JS 与您的自包含对象一起工作。

如:

<!-- ko foreach: Products -->
   <!-- ko if: IsSelected --> // Automatically inherited from parent
    <button class="btn btn-small action remove">
        <i class="icon-minus"></i>
    </button>
    <!-- /ko -->
<-- /ko -->
于 2013-07-05T14:42:28.957 回答
1

for 循环内的代码仅对第一个产品执行。

你应该有这样的东西:

for (var product in products) {
        if (products[product].id() == $productId) {
            return true;
        } 
}
return false;

除了循环之外,无论如何您可能应该使用 ko.utils 中的 arrayFirst,add 函数似乎存在问题。

ng-click 绑定提供 DOM 事件作为第二个参数,因此您可能希望更改 add 方法的签名

function(data,event) { 
    var element = event.target;
}

http://codepen.io/anon/pen/rcwil

self.add = function(model, event) {
    console.log($(event.target));

    var $productId = $(event.target).closest("li").data("productid"),
        $productName = $(event.target).closest("h1");

    self.products.push(new Product($productId, $productName));
};
于 2013-07-05T14:41:22.587 回答