過濾器將表達式的運算結果格式化后呈現給用戶,可以用于視圖模版,控制器或者服務。angularjs有一些內置的過濾器,如果想自己自定義也很容易。
過濾器可以用于視圖模版中的表達式,語法如下:
{{ exPRession | filter }}例如,{{ 12 | currency }}
將數字12用currency過濾器格式化為貨幣輸出,最后的結果為$12.00
。
angularjs的過濾器也支持過濾鏈,語法如下:
{{ expression | filter1 | filter2 | ... }}過濾器還能支持參數輸入,語法如下:
{{ expression | filter:argument1:argument2:... }}例如{{ 1234 | number:2 }}
會將數字1234用number過濾器格式化,根據參數保留小數點后2位,結果為 1,234.00
視圖模版中的過濾器僅僅在輸入改變時才會執行,這比每一次$digest循環都執行一次要高效的多。
但也有兩種例外的情況:
通常只在輸入是基礎類型的過濾器才會在輸入改變時菜執行。如果過濾器對輸入是object的話,每次$digest過濾器都會執行,因為要監測object是否改變會更耗性能。如果過濾器標記為$stateful,那么也會在每次$digest都執行。你也可以在控制器,服務和指令中使用過濾器。
為此,需要將過濾器以<filterName>Filter
的語法注入到相應的controller/service/directive中。例如你想注入number
過濾器就是用numberFilter
,過濾器函數作為控制器的第一個參數注入,過濾器的參數作為控制器函數的第二個參數。
下面的例子所使用的過濾器叫做filter,這個過濾器接受一個數組,并根據過濾條件產生一個子數組。如果在視圖模版中表示的話,可以寫成{{ctrl.array | filter:'a'}}
,將會對數組以a為關鍵字進行全文搜索。然而,如果在視圖模版中這樣做的話,它會在每次$digest都執行過濾器,這會非常耗費性能。因此下面的例子就將過濾器寫在了控制器中,只有在需要的時候才會調用(例如從后端load數據,或者過濾器的表達式需要改變時)
自定義一個過濾器也相當容易,僅僅需要在module中注冊一個新的filter工廠函數。工廠函數會返回一個新的過濾器函數,過濾器的輸入作為過濾器函數的第一個參數,其他過濾器的參數作為過濾器函數的附加參數傳入。
過濾器函數是一個純函數,這意味著給出相同的輸入參數總能得到相同的輸出結果,而不受外界狀態的影響(例如,angularjs的services)。根據這一點,angularjs才能做到僅僅當輸入變化時才去執行一次過濾器。帶狀態帶過濾器也存在,但是非常低效。
過濾器的名字必須是有效的angularjs表達式標識符,例如uppercase,orderBy。名字中不能帶有特殊字符,比如-
和.
都是不允許的,你可以用駱駝命名法(myappSubsectionFilterx
)或者下劃線代替(myapp_subsection_filterx
)。
下面的例子是一個反轉字符串的過濾器,并且根據參數可以選擇大小寫:
<!DOCTYPE html><html><head> <meta charset="uft-8"/> <title></title></head><script src="script/angular.min.js"></script><script> angular.module('myReverseFilterApp', []) .filter('reverse', function() { return function(input, uppercase) { input = input || ''; var out = ''; for (var i = 0; i < input.length; i++) { out = input.charAt(i) + out; } // conditional based on optional argument if (uppercase) { out = out.toUpperCase(); } return out; }; }) .controller('MyController', ['$scope', 'reverseFilter', function($scope, reverseFilter) { $scope.greeting = 'hello'; $scope.filteredGreeting = reverseFilter($scope.greeting); }]);</script><body ng-app="myReverseFilterApp"><div ng-controller="MyController"> <input ng-model="greeting" type="text"><br> No filter: {{greeting}}<br> Reverse: {{greeting|reverse}}<br> Reverse + uppercase: {{greeting|reverse:true}}<br> Reverse, filtered in controller: {{filteredGreeting}}<br></div></body></html>強烈建議不要寫有狀態的過濾器,因為angularjs并不會對其做優化,常常會導致性能問題。很多狀態過濾器可以通過暴露模型的狀態并把它作為過濾器的參數傳入,來達到改為不帶狀態的過濾器。
如果你非要寫一個帶狀態帶過濾器,記得把過濾器標記為$stateful,這樣每次$digest循環都好執行一次或多次過濾器。
<!DOCTYPE html><html><head> <meta charset="uft-8"/> <title></title></head><script src="script/angular.min.js"></script><script> angular.module('myStatefulFilterApp', []) .filter('decorate', ['decoration', function(decoration) { function decorateFilter(input) { return decoration.symbol + input + decoration.symbol; } decorateFilter.$stateful = true; return decorateFilter; }]) .controller('MyController', ['$scope', 'decoration', function($scope, decoration) { $scope.greeting = 'hello'; $scope.decoration = decoration; }]) .value('decoration', {symbol: '*'});</script><body ng-app="myStatefulFilterApp"><div ng-controller="MyController"> Input: <input ng-model="greeting" type="text"><br> Decoration: <input ng-model="decoration.symbol" type="text"><br> No filter: {{greeting}}<br> Decorated: {{greeting | decorate}}<br></div></body></html>上面的例子轉化為無狀態過濾器:
<!DOCTYPE html><html><head> <meta charset="uft-8"/> <title></title></head><script src="script/angular.min.js"></script><script> angular.module('myStatelessFilterApp', []) .filter('decorate', function() { function decorateFilter(input,symbol) { return symbol + input + symbol; } decorateFilter.$stateful = true; return decorateFilter; }) .controller('MyController', ['$scope', function($scope) { $scope.greeting = 'hello'; $scope.symbol="*"; }]) .value('decoration', {symbol: '*'});</script><body ng-app="myStatelessFilterApp"><div ng-controller="MyController"> Input: <input ng-model="greeting" type="text"><br> Decoration: <input ng-model="symbol" type="text"><br> No filter: {{greeting}}<br> Decorated: {{greeting | decorate:symbol}}<br></div></body></html> 如果我的文章對您有幫助,請用支付寶打賞:
新聞熱點
疑難解答