繁体   English   中英

为什么AngularJS过滤器只运行一次?

[英]Why does AngularJS filter only run once?

请考虑以下示例:

  angular.module('app', []).controller('TestController', function($scope) { $scope.getText = function() { console.log('getting text'); return 'text'; }; }).filter('text', function() { return function() { console.log('text filter'); return 'text'; }; }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script> <div ng-app="app" ng-controller="TestController"> <p>{{getText()}}</p> <p>{{'' | text}}</p> </div> 

请注意, getText()函数运行两次,而过滤器只运行一次。 我假设getText()函数运行两次以确保模型现在稳定。 为什么过滤器的行为不一样?

关于这个主题的文档很清楚:

在模板中, 过滤器仅在其输入已更改时执行 这比在每个$ digest上执行过滤器更有效,就像表达式一样。

这是源头。

Cosmin是完全正确的 - 这是一个演示来证明它(巧合的是,它会在某个时刻导致堆栈溢出) - 当调用getText()时,它会为文本过滤器的输入分配一个新值,这会导致它重新评估,这会导致另一个摘要周期,这会导致过滤器重新评估...最终会导致堆栈溢出。


编辑我删除了导致溢出的测试部分 - 这只会使过滤器评估两次,因为getText只被调用两次。

 angular.module('app', []).controller('TestController', function($scope) { $scope.foo = 'bar'; $scope.getText = function() { console.log('getting text'); $scope.foo += 'a'; return 'text'; }; }).filter('text', function() { return function() { console.log('text filter'); return 'text'; }; }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script> <div ng-app="app" ng-controller="TestController"> <p>{{getText()}}</p> <p>{{foo | text}}</p> </div> 

当在模板中使用表达式时,AngularJS首先计算大括号内的材质/文本(插值),然后将值/输出转换为字符串,然后将此字符串值插入HTML元素/属性。

来自AngularJS文档: -在模板中,过滤器仅在其输入已更改时执行。 这比在每个$ digest上执行过滤器更有效,就像表达式一样。

此规则有两个例外:

  • 通常,这仅适用于将原始值作为输入的过滤器。 接收对象作为输入的过滤器在每个$ digest上执行,因为如果输入已经改变则跟踪成本太高。
  • 标记为$ stateful的过滤器也会在每个$ digest上执行。 有关详细信息,请参阅状态过滤器。 请注意,没有AngularJS核心过滤器是$ stateful。

根据文件

过滤器仅在其输入已更改时执行。 这比在每个$digest上执行过滤器更有效,就像表达式一样。

此规则有两个例外:

通常,这仅适用于将原始值作为输入的过滤器。 接收对象作为输入的过滤器在每个$digest上执行,因为如果输入已经改变则跟踪成本太高。

标记为$stateful过滤器也会在每个$digest上执行。 有关详细信息,请参阅状态过滤器。 请注意,没有AngularJS核心过滤器是$stateful

由于您具有不会更改的原始值,因此不必再次执行过滤器。 将空字符串''更改为对象文字{} ,看看会发生什么;)

两个绑定都被检查两次,但您只能看到一个被检查两次。 在过滤器的情况下,输入是''。 Angular只在脏检查时检查过滤器的INPUT( ),并检查两次并比较结果。 所以它不会调用过滤器两次。

对于大括号绑定,表达式的RESULT被检查两次,因此您可以看到您的函数被调用两次。

但是,如果你使输入滤波器的功能像这样你会看到它被称为两次即可像你的花括号绑定和过滤器仍称只有一次。

将过滤器输入更改为函数会显示输入被检查两次,过滤器只被调用一次:

{{getText() | text}}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM