什麼是臟檢測,angular的雙向綁定機製為什麼叫臟檢測,雙向綁定具體細節是怎麼樣的?
01-28
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一個春運遷徙圖(一)