Angular數(shù)據(jù)綁定機制原理
1.Angular.js擴展瀏覽器的事件循環(huán)
瀏覽器持續(xù)等待例如用戶交互這樣的事件。當你在一個<input>標簽里輸入字符之后,這個事件的回調(diào)函數(shù)在JS解釋器中執(zhí)行了其包含的DOM操作,執(zhí)行完畢后,瀏覽器響應(yīng)地對DOM做出了變化。Angular拓展了這個事件循環(huán),使它有時候成為angular context 的執(zhí)行環(huán)境。
2.$watch list
$watch 可以檢測model的變化。每當綁定一個數(shù)據(jù)到view上的時候,$watch隊列就會插入一條對應(yīng)的$watch。例子如下:
controller.js:
app.controller('MainCtrl', function($scope) { $scope.people = [...]; // 假設(shè)長度為10 });
index.html:
<ul> <li ng-repeat="person in people"> {{person.name}} - {{person.age}} </li> </ul>
其中ng-repeat 生成了一個1個$watch,每個person生成了2個$watch,總共是(1+2*10),21個$watch。$watch的生成階段是模板加載完成,也就是linking階段。(angular分為compile和linking階段),Angular會尋找每個directive(上面的例子中ng-repeat和{{}}都屬于directive),然后生成每個$watch。
3.$digest 循環(huán)
當瀏覽器接收到angular context相關(guān)的事件時,$digest循環(huán)就會被觸發(fā)。它由2個小循環(huán)組成,1個處理evalAsync 隊列,另一個處理$watch隊列。$digest進行循環(huán)時,將遍歷$watch隊列,查看是否有數(shù)據(jù)更新過,這種遍歷就叫做dirty-checkin(臟檢查),如果臟檢查發(fā)現(xiàn)有$watch更新,將會觸發(fā)新的臟檢查,直到所有的$watch都沒有更新。這樣就能保證每個model都不會變化。
臟檢查超過10次后會拋出異常防止無限循環(huán)。$digest循環(huán)結(jié)束后DOM會相應(yīng)地發(fā)生變化。其實$digest從字面意義理解就像“消化”的過程一樣,逐漸地把所有營養(yǎng)($watch的變化)都吸收掉。
4.通過$apply 進入 angular context
$apply 決定事件是否進入angular context,使用angualr的自帶directive,比如ng-model,更改綁定的數(shù)據(jù)時,angular會將事件封裝到$apply中。比如,ng-model="name"的輸入框,輸入字符“w”,事件會調(diào)用,$apply("name='w';"),完成$scope中的數(shù)據(jù)更新。
調(diào)用第三方庫時的數(shù)據(jù)綁定
當在angular中調(diào)用jquery,并不能更新jquery綁定的數(shù)據(jù),因為jquery沒有調(diào)用$apply,事件沒有進入angular context,導(dǎo)致$digest沒有執(zhí)行。例子如下:
app.js
app.directive('clickable', function() { return { restrict: "E", scope: { count1: '=', count2: '=' }, template: '<ul style="background-color: lightblue"><li>{{count1}}</li><li>{{count2}}</li></ul>', link: function(scope, element, attrs) { element.bind('click', function() { scope.count1++; scope.count2++; }); } } }); app.controller('MainCtrl', function($scope) { $scope.count1= 0; $scope.count2= 0; });
例子中,每次點擊該元素,預(yù)期count1和count2都會自增1,但實際沒有。其實$scope(ViewModel)已經(jīng)改變,但是沒有強制執(zhí)行$digest。修改click事件如下:
element.bind('click', function() { scope.$apply(function() { scope.foo++; scope.bar++; }); })
經(jīng)過調(diào)用$apply實現(xiàn)了預(yù)期。
5.總結(jié)
angular事件綁定機制如下圖:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Angularjs之ngModel中的值驗證綁定方法
- 解決angular2在雙向數(shù)據(jù)綁定時[(ngModel)]無法使用的問題
- Angular動態(tài)綁定樣式及改變UI框架樣式的方法小結(jié)
- AngularJS中ng-options實現(xiàn)下拉列表的數(shù)據(jù)綁定方法
- 詳解Angularjs 自定義指令中的數(shù)據(jù)綁定
- 淺談Angularjs中不同類型的雙向數(shù)據(jù)綁定
- angularjs 的數(shù)據(jù)綁定實現(xiàn)原理
- AngularJS雙向數(shù)據(jù)綁定原理之$watch、$apply和$digest的應(yīng)用
- 解析Angular 2+ 樣式綁定方式
- 詳解Angular數(shù)據(jù)綁定及其實現(xiàn)方式
相關(guān)文章
Angular CLI在Angular項目中如何使用scss詳解
angular-cli自身支持Scss預(yù)處理器,Scss比css更加方便靈活,而且層次清晰,代碼整潔。下面這篇文章主要給大家介紹了關(guān)于Angular CLI在Angular項目中如何使用scss的相關(guān)資料,需要的朋友可以參考下。2018-04-04詳解angularJs中關(guān)于ng-class的三種使用方式說明
本篇文章主要介紹了angularJs中關(guān)于ng-class的三種使用方式說明,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06AngularJS使用ocLazyLoad實現(xiàn)js延遲加載
這篇文章主要介紹了AngularJS使用ocLazyLoad實現(xiàn)js延遲加載的相關(guān)資料,需要的朋友可以參考下2017-07-07微信+angularJS的SPA應(yīng)用中用router進行頁面跳轉(zhuǎn),jssdk校驗失敗問題解決
本文主要介紹微信+angularJS的SPA應(yīng)用中用router進行頁面跳轉(zhuǎn),jssdk校驗失敗問題解決,這里提供了詳細的操作方式,有需要的小伙伴可以參考下2016-09-09