功能在AngularJS上启动了太多次

时间:2016-02-05 21:44:17

标签: javascript angularjs performance

我有严重的性能问题

我想在列表中显示详细信息,但该函数调用次数过多。

你可以try demo here

这是HTML代码:

<div ng-controller="MyCtrl as ctrl">
<p>Watch your console, then click on a letter. Why "myterious" function is launched so many time ???</p>
<button ng-click="ctrl.setValue('B')">Display B</button>
<button ng-click="ctrl.setValue('C')">Display C</button>
<button ng-click="ctrl.setValue('D')">Display D</button>
  <div ng-repeat="item in ctrl.vitals track by $index">
    <p ng-click="ctrl.toggleDetail($index)" ng-bind="item.name"></p>
    <div ng-show="ctrl.myterious(item.name, ctrl.value)">This should only be display under {{item.name}}</div>
    <div ng-show="ctrl.display[$index]">...</div>
    <br>
  </div>
</div>

还有我的JavaScript代码:

var app = angular.module('myApp',[]);

app.controller('MyCtrl', [function() {
    var self = this;

    self.vitals = [
            {name:'A'},
            {name:'B'},
            {name:'C'},
            {name:'D'},
            {name:'E'},
            {name:'F'},
            {name:'G'},
            {name:'H'},
            {name:'I'},
            {name:'J'},
            {name:'K'}
    ];

    self.display = [];
    self.toggleDetail = function(id) {
            console.log("Toggle launched");
        self.display[id] = !self.display[id];
    };

    self.value = 'B';
    self.setValue = function (val) {
        self.value = val;
    }

    self.myterious = function (a, b) {
        console.log(a + ' ' + new Date().getTime());
        if (a === b) {
            return true;
        } else {
            return false;
        }
    }
}]);

我想知道哪里是问题以及如何修复,因为它是我原始代码的简化。

3 个答案:

答案 0 :(得分:2)

这是因为只要数据(此处为ng-repeat)或循环内使用的任何标志,变量等可能已更改,AngularJS就会重新执行ctrl.vitals循环。

此处,您的mysterious位于ng-if内,因此需要在每次迭代时执行。

还有更多细微之处,本文将更好地解释:Banging Your Head Against an AngularJS Issue? Try This

答案 1 :(得分:2)

所有函数调用的原因是ng-show绑定。每次更新DOM时,它都会运行神秘的功能来确定是否显示该项目。为了避免所有这些函数调用,你的ng-show绑定应该基于静态的东西。见下面的修改示例:

JSFiddle Example

self.vitals = [
      {name:'A', mysterious: false},
      {name:'B', mysterious: true},
      {name:'C', mysterious: false},
      {name:'D', mysterious: false},
      {name:'E', mysterious: false},
      {name:'F', mysterious: false},
      {name:'G', mysterious: false},
      {name:'H', mysterious: false},
      {name:'I', mysterious: false},
      {name:'J', mysterious: false},
      {name:'K', mysterious: false}
    ];

self.setValue = function (val) {
        self.vitals.forEach(function(obj) {
         obj.mysterious = obj.name == val
         })
        self.value = val;
    }

<div ng-repeat="item in ctrl.vitals track by $index">
    <p ng-click="ctrl.toggleDetail($index)" ng-bind="item.name"></p>
    <div ng-show="item.mysterious">
        This should only be display under {{item.name}}  
   </div> </div>

在不知道目标细节的情况下,轻量级函数经常执行以确定dom可见性通常没有任何问题。我唯一一次看到这个问题就是失控。如果您有合理的商业原因来动态计算dom的可见性,请尽可能少地使用它。否则,尽量根据静态(非功能)绑定设计可见性逻辑。

答案 2 :(得分:1)

更准确地说,您的功能被称为两次预期的次数。由于ng-repeat是一个指令,指令可以执行两次或更多次,这是完全正常的。

这已经多次回答,请参阅Why is ng-style function applied twice?以获得一个很好的解释。