ng-bind
單向數據綁定($scope -> view
),用於數據顯示,簡寫形式是 {{}}
。git
1 |
<span ng-bind="val"></span> |
二者的區別在於頁面沒有加載完畢 {{val}}
會直接顯示到頁面,直到 Angular 渲染該綁定數據(這種行爲有可能將 {{val}}
讓用戶看到);而 ng-bind
則是在 Angular 渲染完畢後將數據顯示。angularjs
ng-model
是雙向數據綁定($scope -> view
and view -> $scope
),用於綁定值會變化的表單元素等。github
1 |
<input type="text" ng-model="val" /> |
雙向數據綁定意味着當 view
中有任何數據發生變化會自動地反饋到 scope
的數據上,當 scope
模型發生變化時,view
中的數據也會更新到最新的值。很顯然,這須要一個監控。瀏覽器
事實上,AngularJS 確實在幕後爲 scope
模型上設置了一個 監聽隊列,用來監聽數據變化並更新view
。網絡
每次綁定一個東西到 view
上時 AngularJS 就會往 $watch
隊列裏插入一條 $watch
,用來檢測它監視的 model
裏是否有變化的東西。app
當瀏覽器接收到能夠被 angular context
處理的事件時,$digest
循環就會觸發。$digest
會遍歷全部的 $watch
。框架
好比進行一次 click
操做:函數
1 |
<button ng-click="val=val+1">increase 1</button> |
angular context
$digest
循環開始執行,查詢每一個 $watch
是否變化$scope.val
的 $watch
報告了變化,它會強制再執行一次 $digest
循環。$digest
循環沒有檢測到變化。$scope.val
新值相應部分的 DOM
。$digest
循環不會只運行一次。在當前的一次循環結束後,它會再執行一次循環用來檢查是否有models
發生了變化。ui
這就是髒檢查(Dirty Checking
),它用來處理在 listener
函數被執行時可能引發的 model
變化。所以 $digest
循環會持續運行直到 model
再也不發生變化,或者 $digest
循環的次數達到了 10
次(超過 10
次後拋出一個異常,防止無限循環)。spa
當 $digest
循環結束時,DOM
相應地變化。
$apply
是 $scope
(或者是 direcvie
裏的 link
函數中的 scope
)的一個函數,調用它會強制一次 $digest
循環(除非當前正在執行循環,這種狀況下會拋出一個異常,這是咱們不須要在那裏執行 $apply
的標誌)。
$apply()
和 $digest()
有兩個區別。
1) 最直接的差別是, $apply
能夠帶參數,它能夠接受一個函數,而後在應用數據以後,調用這個函數。因此,通常在集成非 Angular 框架(好比jQuery)的代碼時,能夠把代碼寫在這個裏面調用。
2) 當調用 $digest
的時候,只觸發當前做用域和它的子做用域上的監控,可是當調用 $apply
的時候,會觸發做用域樹上的全部監控。
取決因而否在 Angular 上下文環境(angular context
)。
典型的須要調用 $apply()
方法的場景是:
1) 使用了 JavaScript 中的 setTimeout()
來更新一個 scope model
2) 用指令設置一個 DOM
事件 listener
而且在該 listener
中修改了一些 models
1 |
$scope.setMsg = function() { |
運行這個例子,會看到過了兩秒鐘以後,控制檯確實會顯示出已經更新的 model
,然而,view
並無更新。
在 $scope.getMessage
加入 $apply()
方法。
1 |
$scope.getMessage = function() { |
再運行就 OK 了。
不過,在 AngularJS 中應該儘可能使用 $timeout
Service 來代替 setTimeout()
,由於前者會幫你調用 $apply()
,讓你不須要手動地調用它。
1 |
$timeout(function(){ |
實現一個 click
的指令,相似如下功能:
1 |
<button ng-click="val=val+1">increase 1</button> |
directive
的編寫以下:
1 |
app.directive("inc", function() { |
跟場景一的結果同樣,這個時候,點擊按鈕,界面上的數字並不會增長。但查看調試器,發現數據確實已經增長了。
在 scope.val++;
一行後面添加 scope.$apply();
或者 scope.$digest();
就 OK 了。
1) 無參
1 |
$scope.$apply() |
2) 有參
1 |
$scope.$apply(function(){ |
應該總使用接受一個 function
做爲參數的 $apply()
方法。這是由於當傳入一個 function
到$apply()
中的時候,這個 function
會被包裝到一個 try…catch
塊中,因此一旦有異常發生,該異常會被 $exceptionHandler service
處理。
想象一下若是有個 alert
框顯示錯誤給用戶,而後有個第三方的庫進行一個網絡調用而後失敗了,若是不把它封裝進 $apply
裏面,Angular 永遠不會知道失敗了,alert
框就永遠不會彈出來了。
經常使用的使用方式:
1 |
$scope.name = 'htf'; |
傳入到 $watch()
中的第二個參數是一個回調函數,該函數在 name
的值發生變化的時候會被調用。
若是要監聽的是一個對象,那還須要第三個參數:
1 |
$scope.data.name = 'htf'; |
表示比較的是對象的值而不是引用,若是不加第三個參數 true
,在 data.name
變化時,不會觸發相應操做,由於引用的是同一引用。
轉:http://huangtengfei.com/2015/09/data-bind-of-angularjs/