什麼是臟檢測,angular的雙向綁定機製為什麼叫臟檢測,雙向綁定具體細節是怎麼樣的?


DI / 雙向數據綁定中:

用戶 -&> 內存 :

瀏覽器提供有User Event觸發事件的API,如click,change...等等等;

內存 -&> 用戶:

瀏覽器並沒有提供數據監測的API,故任何內存數據變動(定時、非同步請求、事件觸發...導致的數據變動)都無法被Listen,自然也就沒辦法再處理callback了;

但我們可以基於這些大部分能夠產生數據變動的事件進行封裝(如:click、mouse-enter、Timeout...),在每次事件發生後,執行完事件後,檢查一遍數據的變化,如果數據和上次的值有變化,則執行這個值(註冊時)對應的callback(框架中),這個callback可能是view層的一個數據展現,也可能是一段處理function;

在檢查數據變化的時候,由於你並不知道這個事件是對哪些數據進行了更改,以及這個事件有可能造成事件之外的其他任何地方的數據更改,所以必須進行一次大檢查,將所有「註冊」過的值全部檢查一遍,一次檢查稱為一個周期,每次最少檢查兩遍,因為第二遍用來確認,前一遍的變動中是否有數據的變動,導致了其他數據的變動,如果第二次有變動的話,會再執行一遍,直到最後兩次完全一致,則停止檢查(其實就是個(遞歸(遍歷))的過程),考慮到內存的消耗和死循環的風險,臟檢查每個周期最多遞歸執行10遍,所以在程序結構設計中,盡量避免數據與數據之間的緊耦合;

所以我們看到的

ng-click,ng-change,ng-blur...就是對各類用戶事件的封裝

$timeout,$http,$window,$location...就是對各種JS/API事件的封裝

ng-model,以及控制器中的數據,就是對值的「註冊」

$scope 本質是一個總的事件邏輯的封裝容器,同時抽象為數據載體,

實質上數據都存在於瀏覽器堆內存中

$scope.apply() $scope.digest() 即Angular中的「數據大檢查」的function

所以如果我們使用了非Angular封裝的事件改編數據時,要手動執行一次大檢查

由於Angular這種臟檢查的方法效率不高,如果一個頁面綁定的view超過2000個,就可能存在比較明顯的性能問題,官方稱之為「臟檢查」

類似的Vue.js框架則使用definePropertyAPI來實現數據與視圖的綁定關係

參考:Object.defineproperty實現數據和視圖的聯動


臟檢查機制。

雙向數據綁定是 AngularJS 的核心機制之一。當 view 中有任何數據變化時,會更新到 model ,當 model 中數據有變化時,view 也會同步更新,顯然,這需要一個監控。

原理就是,Angular 在 scope 模型上設置了一個 監聽隊列,用來監聽數據變化並更新 view 。每次綁定一個東西到 view 上時 AngularJS 就會往 $watch 隊列里插入一條 $watch,用來檢測它監視的 model 里是否有變化的東西。當瀏覽器接收到可以被 angular context 處理的事件時,$digest 循環就會觸發,遍歷所有的 $watch,最後更新 dom。


善用搜索

這篇文章應該可以幫到你https://github.com/xufei/blog/issues/10


推薦閱讀:

從1.8萬篇文章中脫穎而出45個最棒的 React.js 學習指南(2018版)
前端開發每周閱讀清單:PWA 將與安卓原生平起平坐、V8 團隊致力於提高 ES2015 特性性能
極樂技術周報(第二十六期)
手把手教你DIY一個春運遷徙圖(一)

TAG:前端開發 | AngularJS |