2017-03-10 57 views
4

考慮下面的例子:爲什麼AngularJS過濾器只運行一次?

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()函數運行兩次以確保模型現在穩定。爲什麼過濾器的行爲不一樣?

回答

5

文檔是對這個問題很清楚:

在模板中,當他們的投入已經改變濾波器只能執行。這比在表達式中對每個$摘要執行過濾器更有效。

Here's the source.

1

當表達式是在模板中使用,然後AngularJS首先計算內括號(插值)的材料/文本,然後將值/輸出轉換爲字符串,然後插入此字符串的值進HTML元素/屬性。

From AngularJS Docs:- 在模板中,過濾器僅在其輸入發生更改時才執行。這比在表達式中對每個$摘要執行過濾器更有效。

有兩種情況例外:

  • 一般而言,這僅適用於取原始值 作爲輸入濾波器。接收對象作爲輸入的過濾器將在每個摘要上執行,因爲如果輸入已更改 ,跟蹤成本太高。
  • 標記爲$ stateful的過濾器也會在每個$摘要中執行。有關更多信息,請參閱狀態過濾器。請注意,沒有AngularJS核心過濾器是$ stateful。當它們的輸入已經改變
0

作爲每documentation

過濾器僅執行。這比在表達式中對每個$digest執行過濾器更有效。

有兩種情況例外:

一般而言,這僅適用於採取原始值作爲輸入濾波器。接收對象作爲輸入的過濾器將在每個$digest上執行,因爲跟蹤輸入是否更改成本太高。

標記爲$stateful的過濾器也會在每個$digest上執行。有關更多信息,請參閱狀態過濾器。請注意,沒有AngularJS核心過濾器是$stateful

由於您有一個原始值不變,過濾器不必再次執行。空字符串''更改爲對象文本{}看看會發生什麼;)

3

科斯明是完全正確的 - 這裏是一個演示,以證明這一點(其中,巧合的是,會造成在某些時候堆棧溢出) - 時的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>

0

兩個綁定正在檢查兩次,但你只能看到一個被檢查兩次。在過濾器的情況下,輸入是「」。角僅檢查輸入(source)到過濾器時髒檢查和它檢查兩次,並比較結果。因此,它不會調用過濾器的兩倍。

對於大括號綁定表達式的結果是兩次檢查,所以你可以看到你被調用函數兩次。

但是,如果您向過濾器輸入一個像this這樣的函數,就會看到它被調用兩次,就像您的花括號綁定一樣,並且過濾器仍然只被調用一次。

改變輸入到功能過濾器顯示輸入被檢查兩次,過濾器被稱爲只有一次:

{{getText() | text}} 
相關問題