在我們的web page,特別是移動設備上,太多的angular $watch將可能導致性能問題。這篇文章將解釋如何去移除額外的$watch提高你的應用程序性能。
$watch如果不再使用,我們最好將其釋放掉,在angular中我們可以自由的選擇在什么時候將$watch從$watch列表中移除。
讓我們來看個示例:
app = angular.module('app', []); app.controller('MainCtrl', function($scope) { $scope.updated = 0; $scope.stop = function() { textWatch(); }; var textWatch = $scope.$watch('text', function(newVal, oldVal) { if (newVal === oldVal) { return; } $scope.updated++; }); });
<body ng-controller="MainCtrl"> <input type="text" ng-model="text" /> {{updated}} times updated. <button ng-click="stop()">Stop count</button> </body>
$watch函數會返回一個釋放$watch綁定的unbind函數。所以當我們不再需要watch改變的時候,我們可以easy的調用這個函數釋放$watch。
由靜態數據構成的頁面
讓我假想我們要創建一個會議session預約的頁面,頁面像如下結構:
app.controller('MainCtrl', function($scope) { $scope.sessions = [...]; $scope.likeSession = function(session) { // Like the session } });
<ul> <li ng-repeat="session in sessions"> <div class="info"> {{session.name}} - {{session.room}} - {{session.hour}} - {{session.speaker}} </div> <div class="likes"> {{session.likes}} likes! <button ng-click="likeSession(session)">Like it!</button> </div> </li> </ul>
假想這是一個大型的預約,一天會有30個sessions。這里會產生多少個$watch?這里每個session有5個綁定,額外的ng-repeat一個.這將會產生151個$watch。這有什么問題?每次用戶“like”一個session,angular將會去檢查name是不是被改變(其他的屬性也相同)。
問題在於除了例外的“like”外,所有的數據都是靜態數據,這是不是有點浪費資源?我們能夠100%保證我們的數據不會改變,既然這樣為什么我們讓angular要去檢查是否改變呢?
解決方案很簡單。我們移除永遠不會改變的$watch。$watch在第一非常重要,它用靜態信息生產更新了我們的DOM結構,但是在此之后,它監聽了一個永遠不會被改變的常量,這明顯是很大的浪費資源。
如果你相信我了的話,會我們能怎么去解決呢?幸運的是,這有個nice guy在我們之前也問了自己這個問題,並創建了一系列的指令實現這個:Bindonce.
Bindonce
Bindonce是一系列綁定但是不帶watch的指令集,這很完美的符合了我們的需求。
讓我們用Bindonce重新實現我們的view:
<ul> <li bindonce ng-repeat="session in sessions"> <div class="info"> <span bo-text="session.name"></span> - <span bo-text="session.room"></span> - <span bo-text="session.hour"></span> - <span bo-text="session.speaker"></span> </div> <div class="likes"> {{session.likes}} likes! <button ng-click="likeSession(session)">Like it!</button> </div> </li> </ul>
為了讓示例能夠工作,我們必須引入bindonce到我們的應用程序。
app = angular.module('app', ['pasvaz.bindonce']);
在這里我們將angular表達式換位了bo-text指令。這指令將會綁定我們的model,知道更新DOM,然后去掉綁定。這樣我就可以顯示view但是移除不必要的餓綁定了。
在此例中每個session只有一個$watch綁定,所以這里用31個綁定替代了151個綁定。我們正確的使用bingonce將會為我們的應用程序大量減少$watch綁定。
總結
當我們的性能無法避免的需要優化的時候,bindonce能夠幫助脫離$watch的性能瓶頸。在bindonce中還有很多的指令,我可以從這里搜索到:https://github.com/Pasvaz/bindonce#attribute-usage