【问题标题】:Can a filter be an impure function?过滤器可以是不纯函数吗?
【发布时间】:2015-04-18 03:10:46
【问题描述】:

以下作品

<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 并不“知道”它应该重新调用过滤器函数。这样做只是因为单击会重新启动摘要外观并重新执行所有操作。

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

我的第二个问题:如果在每个摘要循环上都重新调用过滤器功能,有什么方法可以阻止这种行为吗?我可以告诉它,除非参数已经改变,否则不要再调用这个函数,你会得到相同的答案吗?还是我必须手写?

【问题讨论】:

  • 是的,第一个选项每次都会运行,而不是它,我喜欢在 angular 指令上执行它,它将更新keyup 事件的输入。您可以使用ng-model-options 执行第二个行为
  • 顺便说一句,我想说,一般来说,过滤器不应该依赖于状态。不是说不能有例外,但确实感觉不对。

标签: angularjs


【解决方案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;
}])

【讨论】:

  • 谢谢。有没有办法让模型在过滤器和 Angular 之间显式而不涉及客户端代码?我不想每次都写{{"Hello" | myFilter:capitalize }},因为大写是唯一的合法值(嗯,在我的实际情况中是这样)。
  • 如果您希望它基于整个应用程序的一个全局条件,这正是$stateful 的用途。尽管有警告,但这可能是您想要的路线,因为听起来您不想每次都指定参数。我对原始代码的唯一建议改进是使用服务来获取和设置全局值而不是根范围。
  • 问题是,我有 很多 次使用过滤器,并且全局条件几乎从未改变。现在,我正在使用直接监视条件的指令,并且我正在考虑切换到过滤器,但现在听起来非常昂贵。
猜你喜欢
  • 1970-01-01
  • 2016-05-22
  • 2019-12-14
  • 1970-01-01
  • 2021-06-21
  • 1970-01-01
  • 2018-12-22
  • 2018-08-05
  • 2017-01-22
相关资源
最近更新 更多