AngularJS的數據雙向綁定是怎么實現的?

??: 關于 AngularJS 的數據綁定

單向綁定(ng-bind) 和 雙向綁定(ng-model) 的區別:
ng-bind 單向數據綁定($scope -> view),用于數據顯示,簡寫形式是 {{}}
<span ng-bind="val"></span>
兩者的區別在于頁面沒有加載完畢 {{val}}會直接顯示到頁面,直到 Angular 渲染該綁定數據(這種行為有可能將 {{val}}讓用戶看到);而 ng-bind則是在 Angular 渲染完畢后將數據顯示。ng-model是雙向數據綁定($scope -> view and view ->$scope),用于綁定值會變化的表單元素等。<input type="text" ng-model="val" />

之前的總結: 2.4.0 angular雙向數據綁定

有三個概念:

  • $digest():臟值檢查循環
  • $watch:添加監聽
  • $apply:提供上下文執行表達式

雙向數據綁定(bi-directional)意味著如果視圖改變了某個值,數據模型會通過臟檢查觀察到這個變化,而如果數據模型改變了某個值,視圖也會依據變化重新渲染。

當你寫下表達式如{{ aModel }}時,AngularJS在幕后會為你在scope模型上設置一個watcher,它用來在數據發生變化的時候更新view。這里的watcher和你會在AngularJS中設置的watcher是一樣的

對于所有綁定給同一$scope元素的UI對象,只會添加一個$watch到$watch列表中(一個數據一個$watcher,對象會有一個,里面的值還會有,數組中每個對象都有一個 )。這些$watch列表會在$digest循環中通過一個叫做“臟值檢查”的程序解析

  • 假設你在一個ng-click指令對應的handler函數中更改了scope中的一條數據,
  • 此時AngularJS會自動地通過調用$digest()來觸發一輪$digest循環。
  • 當$digest循環開始后,它會觸發每個watcher。
  • 這些watchers會檢查scope中的當前model值是否和上一次計算得到的model值不同。
  • 如果不同,那么對應的回調函數會被執行。調用該函數的結果,就是view中的表達式內容(譯注:諸如{{ aModel }})會被更新。

除了ng-click指令,還有一些其它的built-in指令以及服務來讓你更改models(比如ng-model,$timeout等)和自動觸發一次$digest循環。如下:

談起angular的臟檢查機制(dirty-checking), 常見的誤解就是認為: ng是定時輪詢去檢查model是否變更。 其實,ng只有在指定事件觸發后,才進入$digest cycle:

  • DOM事件,譬如用戶輸入文本,點擊按鈕等。(ng-click)
  • XHR響應事件 ($http)
  • 瀏覽器Location變更事件 ($location)
  • Timer事件($timeout, $interval)
  • 執行$digest()或$apply()
    上述事件發生->$digest()循環->觸發每個watcher->watcher檢查scope中的當前model值和上一次計算得到的model值是否不同->如果不同,那么$watch()對應的回調函數會被執行->調用該函數的結果,就是view中的表達式內容(譯注:諸如{{ aModel }})會被更新

angularJS并不直接調用$digest(),而是調用$scope.$apply(),后者會調用$rootScope.$digest()。因此,一輪$digest循環在$rootScope開始,隨后會訪問到所有的children scope中的watchers。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容