AngularJS 提供的 filter 無法滿足我們顯示的種種需求。
所以完成一個專案,大部分都會需要自己寫 filter 的。
範例:
後端傳來的值是
obj {
user_installed: true
}
我們想要畫面呈現的是 "已安裝"。
<div> {{ obj.user_installed | userInstalled }}</div>
app.filter('userInstalled', function () {
// obj.user_installed 的值
return function (isInstalled) {
// 判斷後並回傳對應的 string
return isInstalled ? '已安裝': '還沒安裝';
}
})
顯示使用者的 ranking
後端會傳數字,可是前端要用愛心表示 ranking。
app.filter('myLove', function () {
return function (num) {
if (angular.isNumber(num)) {
var str = '';
for (var i = 0; i < num; i++) {
str += '❤';
}
return str;
}
return '';
}
})
客製化 filter 能做的除了單純轉換 String 樣式,還可過濾 array, date, 等不同 type 的參數。
(ex: 昨天陣列 filter 範例)
也可以在 filter 中,用 DI 作法實作複數篩選。(dependency injection $filter module)
ex: 畫面上的價錢自動加上 10,000
app.filter('updateMoney', function ($filter) {
return function (money) {
return $filter('currency')(money + 10000);
}
})
完整範例:http://plnkr.co/edit/1ABg67uVGzJeQ4kRuaww?p=preview
還有另外作法(註一)
可是真正的 money value 還是會維持原本的 2,000。
不必擔心過了 filter 後,value 會被修改的問題。
由於 AngularJS dirty-check 的關係,filter 會使 filter function 跑兩次。(註二)
(嚴格來說,是任何的 data-binding 都會跑兩次以上)
所以我建議 filter 中的邏輯不能複雜,會造成效能問題。
(請想像有超過一萬筆資料的陣列跑 loop 兩次的後果..)
3. 使用 Lo-Dash 增加效能
我的習慣是陣列的 filter,我幾乎會改放在 controller 裡,並用 Lo-Dash 做篩選。
因為 Lo-Dash 的過濾陣列動作比較單純,
而 AngularJS 的 filter 因要符合 AngularJS 的總總特性,還會多做些檢查跟跑 methods。
參考 jsperf http://jsperf.com/angularvslodashfilter
<div ng-repeat=“item in myList()"></div>
app.controller(‘myCtrl’, function ($scope, $filter) {
var ctrl = this;
ctrl.myList = function () {
return _.sortBy(list, function (item) {
return item.price;
});
}
})
4. 畫面上的值是固定的,就不要用 Filter 了!
假如畫面的值在一開始 controller 初始化後,你就知道不會改變了。(static value)
建議直接在 controller 裡完成初始化的動作後就不要再操作了。
就是不用包在 function 裡,也不用 inline-filter 去做任何會發生 data-binding 的操作。
(也可以使用 bindonce + filter 做事情,這是另外一個故事了..)
<!— 不會改變 —>
<div ng-repeat=“item in myList"></div>
app.controller(‘myCtrl’, function ($scope, $filter) {
var ctrl = this;
ctrl.myList = _.sortBy(list, function (item) {
return item.price;
}
})
**(註一)
這個例子也可以使用在 html 上呼叫多個 filter 的方式
範例:
<div>{{Ctrl.oMoney | updateMoney | currency }}</div>
app.filter('updateMoney', function ($filter) {
return function (money) {
return money + 10000;
}
})
** (註二 參考文章)
http://www.bennadel.com/blog/2489-how-often-do-filters-execute-in-angularjs.htm