如果数组包含值,则Angular有条件地应用类

时间:2015-03-04 19:24:51

标签: javascript arrays angularjs angularjs-ng-repeat

我有一个product变量,它包含一个嵌套的分层产品数组,例如:

Product
     - cat_id: 1
     - name: Some Product
     - Children
          - Child Product 1
          - Child Product 2
                  - Children
                      - I can also have more children here
                      - And another
          - Child 3
Product 2
     - cat_id: 2
     - name: Some other Product
     - Children
         - A child product
         - another 

我还有另一个变量,即已购买的产品数组。

我想要做的是如上所示显示完整的产品列表,但如果用户购买了它,则申请上课。

到目前为止我在这里:

<ul>
    <li ng-repeat="product in all_products track by product.cat_id">
        {{ product.cat_name }}
            <ul ng-if="product.children.length>0">
                <li ng-repeat="l1_child_product in product.children track by l1_child_product.cat_id">

                    {{ l1_child_product.cat_name }}
                    <ul ng-if="l1_child_product.children.length>0">
                        <li ng-repeat="l2_child_product in l1_child_product.children track by l2_child_product.cat_id">
                            {{ l2_child_product.cat_name }}
                        </li>
                    </ul>
                </li>
            </ul>
    </li>
</ul>
</div>

我想要做的是为每个

  • 应用该类,如果第二个数组的内容包含当前产品的cat_id,例如:

    <li ng-repeat="product in all_products track by product.cat_id" ng-class="foreach(otherarray as owned){ if(owned.cat_id==product.cat_id){ 'some_class' } }">
    

    我仍然对Angular很新,所以我想知道实现这一目标的正确方法。

    我目前正将我的应用程序从纯粹的服务器端移植到静态前端到Angular。我能够在我的旧应用程序中使用带有条件语句的几个嵌套for循环来非常快速地执行这种逻辑。

    但是,对于Angular,这似乎会导致应用程序陷入非常缓慢的速度。

    我听说过Angular使用的脏检查,我认为我遇到了因为我的数据集通常相当大而导致的瓶颈(大约250个产品,约有40个购买) ,但页面上显示最多20个用户。使用Angular时,什么是避免这些性能问题的好方法?

    更新

    这是我目前使用的代码:

    <div class="row" ng-repeat="user in ::users">
    
    <script type="text/ng-template" id="product_template.html">
        {{ ::product.cat_name }}
        <ul ng-if="product.children">
            <li ng-repeat="product in ::product.children track by product.cat_id"
                ng-include="'product_template.html'"></li>
        </ul>
    </script>
    
    <ul>
        <li ng-repeat="product in ::all_products track by product.cat_id"
            ng-include="'product_template.html'"></li>
    </ul>
    
    
    <table>
        <tr ng-repeat="licence in ::user.licences">
            <td>{{::licence.product.cat_name}}</p></td>
            <td>{{::licence.description}}</td>
            <td>{{::licence.start_date}}</td>
            <td>{{::licence.end_date}}</td>
            <td>{{::licence.active}}</td>
        </tr>
    </table>
    </div>
    

    这给出了所需的输出:

    • 迭代用户
    • 迭代所有可用产品
    • 显示所有购买(许可证)的列表

    然而,它非常缓慢。我只是定时页面加载,解析所有数据并显示它需要32秒(数据在大约100ms后可用)。

    我使用new ::语法来阻止大量的双向绑定,但这似乎并没有提高速度。

    有什么想法吗?

  • 3 个答案:

    答案 0 :(得分:1)

    您的问题分为两部分:

    • 如何递归显示产品及其子女?
    • 以有效的方式,如果已购买产品,如何添加课程?

    显示产品及其子女

    上一个关于Rending a Tree View with Angular的问题已经回答了这个问题。

    有效添加已购买的课程

    您目前的低效率是通过查看每个产品的otherarray而产生的。

    关于如何改进这一点有各种解决方案,但我认为最简单的改变是使用{}代替数组来跟踪购买的产品。

    { cat_id: true }

    有关使用ObjectHash的原因,请Finding Matches between Arrays更快地查看此问题。

    组合解决方案

    显示产品及其子女

    <script type="text/ng-template" id="product_template.html">
      {{ product.cat_name }}
      <ul ng-if="product.children">
        <li ng-repeat="product in product.children"
        ng-include="'product_template.html'"
        ng-class="{ purchased : product.purchased }"></li>
      </ul>
    </script>
    
    <ul ng-app="app" ng-controller="ProductCtrl">
      <li ng-repeat="product in all_products"
      ng-include="'product_template.html'"
      ng-class="{ purchased : purchasedProducts[product.cat_id] }"></li>
    </ul>
    

    只需添加一个已购买的课程。 otherarray - &gt; purchasedProducts对象

    我不确切地知道otherarray的确切位置,但简单的转换如下:

    var purchasedProducts = {};
    for (var i = 0; i < otherarray.length; i++) {
      var cat_id = otherarray[i];
      purchasedProducts[cat_id] = true;
    }
    

    答案 1 :(得分:0)

    请记住,ng-class可以是函数调用。

    答案 2 :(得分:0)

    从Angular 1.3开始,有原生的Bind Once支持。当迭代大量项目时,你可以消除不会改变的静态元素的观察者。

    例如:

    <li ng-repeat="product in ::all_products track by product.cat_id">
    

    将遍历all_products数组一次以填充ngRepeat,但不会继续绑定到$watch以进行更改跟踪。智能使用::可以大幅提升效果。

    此外,将ng-class=转换为函数而不是内联表达式评估可以提高性能并使您可以更好地控制输出。