过滤器可以是不纯的功能吗?

时间:2015-04-17 18:51:40

标签: angularjs

以下有效

<script>
angular.module('myApp', [])
.filter('myFilter', ['$rootScope', function($rootScope) {
  return function(v) {
     return $rootScope.capitalize ? (v && v.toUpperCase()) : v;
  };
}])
.controller('myController', ['$rootScope', '$scope', function($rootScope, $scope) {
  $scope.flipCapitalize = function() {
    $rootScope.capitalize = !$rootScope.capitalize;
  }
}]);
</script>
{{"Hello" | myFilter }}

<div ng-controller="myController">
  <button ng-click="flipCapitalize()">flip</button>
</div>

当您按下按钮时,屏幕上的“Hello”字样在混合大小写和大写字母之间翻转。

但是Angular并不“知道”它应该重新调用过滤器函数。它只是这样做,因为点击重新启动摘要外观并重新执行所有操作。

我的问题:这种行为有保障吗?我是否可以始终假设过滤器将在摘要循环中重新调用,并且我可以使用我能找到的任何范围内的任何数据?或者我是否幸运?

我的第二个问题:如果在每个摘要循环中重新调用过滤器函数,是否有某种方法可以打败这种行为?我可以告诉它,除非参数已经改变,不要再调用这个函数,你会得到相同的答案吗?或者我必须手工记忆?

1 个答案:

答案 0 :(得分:1)

根据angular docs,如果您想保证过滤器正常工作,则需要使用过滤器的$stateful属性将其标记为“有状态”。

  

强烈建议不要编写有状态的过滤器,因为Angular无法优化这些过滤器的执行,这通常会导致性能问题。只需将隐藏状态作为模型公开并将其转换为过滤器的参数,就可以将许多有状态过滤器转换为无状态过滤器。

     

如果您确实需要编写有状态过滤器,则必须将过滤器标记为$ stateful,这意味着它将在每个$ digest循环期间执行一次或多次。

因此,您应该将过滤器标记为有状态以保证该行为:

.filter('myFilter', ['$rootScope', function($rootScope) {
  var filter = function(v) {
     return $rootScope.capitalize ? (v && v.toUpperCase()) : v;
  };
  filter.$stateful = true;
  return filter;
}])