ng-if被调用的次数超过它应该的次数

时间:2016-01-27 14:33:33

标签: angularjs mongodb meteor angular-meteor

我尝试根据所选类别过滤某些频道。

我有channel in channels的ng-repeat,其ng-if="hasCategory(channel.category)

这是文件:

db.channels.find().pretty()
{
    "_id" : "2kj9GK8jE9yHezoWb",
    "name" : "example name",
    "logo" : "path/to/image.svg",
    "number" : 2,
    "category" : [
        "Broadcast",
        "Premium"
    ],
    "tags" : "example tag tags"
}

这是处理ng-if:

的功能
$scope.hasCategory = function (categoryNameArray) {
  console.log('thisisbeingcalled');
  var e = _.indexOf(categoryNameArray, $scope.activeCategory);
  if (e === -1) {
    return false;
  } else {
    return true;
  }
};

这就是我设置活动类别的方式:

$scope.setCategory = function (name) {
  $scope.activeCategory = name;
};
单击视图中的按钮发送的

<section layout="row" layout-align="center center" layout-wrap ng-init="activeIndex; activeCategory">
  <md-button flex="auto" flex-sm="45" flex-xs="100" ng-repeat="kit in kits | orderBy: 'order'" ng-class="{active: (activeIndex.index == $index)}" class="md-raised">
    <a href="" ng-click="activeIndex.index = $index; setCategory(kit.name);" class="bold">{{kit.name}}</a>
  </md-button>
</section>

这里是套件文档架构:

db.kits.find().pretty()
{ "_id" : "k7JFX6DHu5GYnyer3", "name" : "Broadcast", "order" : 1 }
{ "_id" : "KrKRm4gysw5sfQnnr", "name" : "Premium", "order" : 2 }
{ "_id" : "dieukQ3NRsA44CSns", "name" : "Ultimate", "order" : 3 }

现在我只有一个通道来测试它,但每次单击按钮更改类别时,即使在页面启动时(第一次加载),$scope.hasCategory函数也会被多次调用< / p>

enter image description here

我还有一个搜索栏来搜索当前类别中的频道,我不确定这是否会对此产生影响。

<input type="text" ng-model="queryname" ng-model-options="{debounce: 500}">

现在,当我有超过100个频道时,这会变得非常滞后,ng-if会被调用超过10k次,这会使页面冻结很长一段时间。

我该怎么做才能解决这个问题?

修改

忘记添加ng-if的位置:

<md-card flex="15" flex-xs="40" class="slide-up" layout="column" ng-repeat="channel in channels | orderBy: 'number' | filter: queryname" ng-if="hasCategory(channel.category)" ng-init="channel.edit = false">
  <md-card-header ng-show="channel.edit == false">
    <img ng-src="{{channel.logo}}" alt="">
  </md-card-header>
  <md-card-header-text ng-show="channel.edit == false">
    <span class="md-subhead dark-blue" layout="row" layout-align="center" layout-margin>{{channel.number}}</span>
  </md-card-header-text>
</md-card>

1 个答案:

答案 0 :(得分:6)

每个摘要循环都会调用ng-if。问题是它包含一个涉及函数调用的表达式。 Angular无法知道表达式的结果何时可能发生变化,因此每次都会调用它。

更好的选择是在每个通道中设置一个标志,并使用ng-if来测试相关标志。然后,您只需更新$scope.activeCategory更改时的标记,您可以使用代码设置类别或使用$scope.$watch()自动触发它。

e.g。

$scope.setCategory = function (name) {
  $scope.activeCategory = name;
  for (var index=0; index < $scope.channels.length; index++) {
      $scope.channels[index].hasCategory = hasCategory($scope.channels[index].category, name);
  }
};

function hasCategory(categoryNameArray, name) {
  console.log('thisisbeingcalled');
  var e = _.indexOf(categoryNameArray, name);
  if (e === -1) {
    return false;
  } else {
    return true;
  }
}

然后在你的模板中:

<md-card flex="15" flex-xs="40" class="slide-up" layout="column"
    ng-repeat="channel in channels | orderBy: 'number' | filter: queryname"
    ng-if="channel.hasCategory"
    ng-init="channel.edit = false">
  <md-card-header ng-show="channel.edit == false">
    <img ng-src="{{channel.logo}}" alt="">
  </md-card-header>
  <md-card-header-text ng-show="channel.edit == false">
    <span class="md-subhead dark-blue" layout="row" layout-align="center" layout-margin>{{channel.number}}</span>
  </md-card-header-text>
</md-card>

应该更有效率。