標籤:
這篇,講一下angularjs的ng-bind指令,多個控制器,以及手動觸發angularjs的髒檢查,我直接把代碼貼,順著代碼講。
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title></head><body ng-app="ngApp"><div ng-controller="firstController"> <input type="text" ng-model="name"/> <div ng-bind="name"></div> <div ng-controller="secondController"> <input type="text" ng-model="name"/> {{name}} {{date}} </div></div></body><script type="text/javascript" src="../public/javascripts/lib/angular.js"></script><script type="text/javascript"> alert(123); var ngApp=angular.module(‘ngApp‘, []); ngApp.controller("firstController",function($scope){ $scope.name="xixi"; }); ngApp.controller("secondController",function($scope){ setInterval(function(){ $scope.$apply(function(){ $scope.date=new Date(); }); },1000); });</script></html>
1、ng-bind:在使用angularjs運算式{{name}}時,如果angularjs還沒載入完畢,我們會看到頁面直接把angularjs運算式當作字串給渲染到html,這樣顯示不友好。這裡推薦使用ng-bind,ng-bind在angularjs沒有載入完畢的時候是不會解析執行的,一旦angularjs載入完畢的時候就會執行。運行上面的代碼,在彈出alert的時候,起碼沒有使用ng-bind的地方就會直接顯示angularjs的運算式,而是用了ng-bind的地方則是什麼沒有顯示,關閉alert後,頁面就顯示了正常的資料。
2、多個控制器:上面代碼中,我們定義了兩個控制器,firstController跟secondController,其中secondController是位於第一個firstController裡面的,secondController裡面沒有name屬性。我們在運行代碼的時候,發現,第一個跟第二個控制器所控制的範圍都顯示了name的值,這是為什麼呢?這其實跟javascript的範圍鏈是一樣的。secondController裡面沒有找到name,就會往上一級找,剛好在firstController裡面找打了name,所以兩個控制器掌控的範圍都顯示了name的值。上面代碼運行後,我們在第一個表單輸入數值,發現,所以使用了name的地方都跟著變。而當在第二個表單,也就是第二個控制器掌控的範圍內,輸入數值改變第二個控制器的model後,再在第一個表單輸入值後,發現第二個的值不在變化了,這又是為什麼呢?因為secondController此時內部會聲明了name,而整個secondController啟動並執行代碼就在自己的範圍裡面,同時由於上級的範圍是訪問不到下級範圍的,所以不會影響secondController的值。注意,在第二個表單輸入值,輸入第一個表單的值,為啥第二個表單也跟著變呢?那是因為第二個表單往上面範圍尋找name變數,而不是第一個控制器所影響的。
3、angularjs的apply:前面幾篇的一些例子裡面講到,我們在控制器裡面更改$scope的屬性值,view也跟著變。但是,如果我們把上面代碼的setInterval裡面的$scope.$apply去掉,直接寫上$scope.date=new Date(),這樣頁面的時間是不會改變的。這是因為控制器裡面的$scope的屬性值了,卻沒有進行屬性的檢查。大家應該知道,通常要知道一個變數是否更改,一般有兩種情況,一是通過set調用賦值,二是通過髒檢查,把原來的對象複製一份快照,在特定的時間,遍曆現在的對象屬性同快照的對象的屬性一個一個的比較。這種策略要保留兩份變數,且遍曆對象比較每一個屬性,這是有一定的效能問題的。在angularjs中,使用的就是髒檢查這種策略。
4、angularjs的髒檢查策略:
a) angularjs不會檢查每一個對象,只有添加到html中的對象,才會添加為檢查對象,即一個watcher。
b) angularjs也不會檢查每一個屬性,只有屬性被綁定以後,這個屬性才會添加為檢查屬性。
c) angularjs在初始化的時候,會為每一個對象的綁定屬性添加為監聽對象,即一個對象綁定了n個屬性,則同時也就是添加了n個watcher。
5、angularjs什麼時候會進行髒檢查呢?在angularjs系統中所有的方法,比如在controller初始化的時候,所以ng-開頭的指令執行後都會觸發髒檢查。
6、$apply手動觸發髒檢查。注意的時候,$apply只是進入了angularjs的執行內容,真正觸發髒檢查的是$digest。在使用$apply的時候,如果不帶參數,則會檢查$scope裡所有監聽的屬性,所以在使用的時候,建議帶上參數。
7、上面我們提到,出發髒檢查的是$digest()方法,這個方法會出發$scope以及所有的子$scope的髒檢查,而髒檢查又出發了watcher,這樣整個angularjs的資料雙向繫結的機制就活起來了。雖然說觸發髒檢查的是$digest方法,但是不建議直接使用,而是建議使用$apply。$apply不是直接把資訊傳遞給$digest的,而不是通過$eval這層過濾,如果$apply帶的運算式不合法的話,$eval就會把錯誤發送給$exceptionHandler,只有合法的才會觸發$digest,這樣更加安全。
本篇就寫到這,後續會接著寫angularjs其他方面的知識。
04、AngularJS的ng-bind、多個控制器和apply