admin管理员组文章数量:1384812
Consider the following example:
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=".6.2/angular.min.js"></script>
<div ng-app="app" ng-controller="TestController">
<p>{{getText()}}</p>
<p>{{'' | text}}</p>
</div>
Consider the following example:
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./ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<div ng-app="app" ng-controller="TestController">
<p>{{getText()}}</p>
<p>{{'' | text}}</p>
</div>
Notice that the getText()
function runs twice whereas the filter only runs once. I assume the getText()
function runs twice to make sure the model is now stable. Why not the same behavior for the filter?
5 Answers
Reset to default 5The documentation is pretty clear on this subject:
In templates, filters are only executed when their inputs have changed. This is more performant than executing a filter on each $digest as is the case with expressions.
Here's the source.
Cosmin is exactly right - and here's a demo to prove it (which, coincidentally, will cause a stack overflow at some point) - when getText() is called, it assigns a new value to the input of the text filter, which causes it to re-evaluate, which causes another digest cycle, which causes the filter to reevaluate... which eventually causes something like a stack overflow.
EDIT I removed a testing portion that was causing the overflow - this will only have the filter evaluate twice, since getText is called only twice.
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./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>
When an expression is used in a template, then AngularJS first evaluates the material/text inside braces (Interpolation) and then converts the value/output to string and then insert this string value into the HTML element/attribute.
From AngularJS Docs:- In templates, filters are only executed when their inputs have changed. This is more performant than executing a filter on each $digest as is the case with expressions.
There are two exceptions to this rule:
- In general, this applies only to filters that take primitive values as inputs. Filters that receive Objects as input are executed on each $digest, as it would be too costly to track if the inputs have changed.
- Filters that are marked as $stateful are also executed on each $digest. See Stateful filters for more information. Note that no AngularJS core filters are $stateful.
As per documentation,
Filters are only executed when their inputs have changed. This is more performant than executing a filter on each
$digest
as is the case with expressions.There are two exceptions to this rule:
In general, this applies only to filters that take primitive values as inputs. Filters that receive Objects as input are executed on each
$digest
, as it would be too costly to track if the inputs have changed.Filters that are marked as
$stateful
are also executed on each$digest
. See Stateful filters for more information. Note that no AngularJS core filters are$stateful
.
Since you have a primitive value which doesn't change, the filter doesn't have to execute again. Change the empty string ''
to an object literal {}
and see what happens ;)
Both bindings are being checked twice, but you can only see one being checked twice. In the case of the filter, the input is ''. Angular is only checking the INPUT (source) to the filter when dirty checking and it checks it twice and pares results. So it doesn't call the filter twice.
For the curly brace binding, the RESULT of the expression is checked twice, and so you can see your function being called twice.
But if you make the input to the filter a function like this you'll see it's called twice just like your curly brace binding and the filter is still called only once.
Changing the filter input to a function shows that input is checked twice and filter is called just once:
{{getText() | text}}
本文标签: javascriptWhy does AngularJS filter only run onceStack Overflow
版权声明:本文标题:javascript - Why does AngularJS filter only run once? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744534741a2611244.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论