Angular(06)- 為什么數據變化,綁定的視圖就會自動更新了?


這里提一點,前端三大框架(Angular,React,Vue)的數據驅動來更新視圖的原理,即 MVVM 的實現。
為什么數據發生變化,綁定的視圖就會刷新了呢?

以下是我的個人理解,僅供參考:

在還是 jQuery 的時代,當在 js 中改變了某個變量的數據,而這個變量是需要在 Html 中顯示出來的。那么,這個時候,我們的做法也就是通過 DOM 先獲取到顯示該變量的視圖元素,然后借助 DOM API 來更新這個視圖元素,是吧。這是原始的方式。

那么,不管三大框架都做了些什么,MVVM 的實現原理是什么,它們最終其實也都還是要通過操縱 DOM API 來更新視圖元素,與原始方式的區別就是,這部分操縱 DOM 的工作,由框架來負責,我們無需關心了,只需要關心數據的變化工作即可。

好處就是,我們可以更關注於業務邏輯的編程,而無須再去為如何操縱 DOM 樹而煩惱。

那么,既然框架要來幫我們處理這部分工作,它們實現的關鍵點就在於,如何知道,我們對數據進行了更新?

什么意思?也就是說,這部分工作由我們自己來做時,我們是能夠明確的知道什么時候該去操縱 DOM 樹了,不就是我們對數據進行更新的時刻嗎。但,框架並不知道我們什么時刻會對數據進行更新。

所以,回想一下,你在使用三大框架時,是不是每個框架基本都有一些注意事項,或者說它的規定?

比如說:

react 要求修改 state 局部變量時,得通過 this.setState(...)
vue 要求得聲明在 data 中的變量,當它變化時才會被追蹤到,以更新視圖

為什么這些框架會有這些要求,或者說這些規定?
因為它需要知道我們到底什么時刻會去對數據進行更新啊。

對於 react 來說,當我們需要更新變量的數據值時,都通過調用它的方法,那么,它自然就知道我們什么時候更新了數據了。

對於 vue 來說,雖然我們更新數據時是直接對變量進行賦值操作,但實際上,聲明在 data 中的這些變量,都會被轉換成存取器屬性,也就是 set 和 get。那么,當我們直接對變量的賦值操作,其實會去執行 set 的內部邏輯,而 vue 只需要在這里就可以獲取我們更新數據的時機了。

那么,對於 Angular 呢?好像使用 Angular 過程中,並沒有需要遵循什么規定。

這是因為,Angular 的實現原理並不類似於 react 和 vue。

react 和 vue 的原理類似於主動通知的模式,也就是,當我發生變化了,那我就通知你一下,你就需要去做些更新處理了。

Angular 的原理,類似於被動輪詢的模式。也就是,你不知道我什么時候會變化,那么你就在我有可能會變化的情況下,不斷的讀取我的值,比對一下,看看有沒有發生變化。

驗證 Angular 的這種原理的猜測很簡單,你在頁面上某個元素綁定個方法,方法內打個日志,然后你滑動下頁面試試看,看看日志是不是一直在輸出。

總結一下:
三大框架實現的原理其實有所差異
react 是通過調用 setState() 方式來告知視圖刷新;
vue 是通過將聲明在 data 中的數據屬性轉換為存取器數據(set 和 get)的方式,來監聽數據變化的時機;
angular 則是在會觸發視圖變化的情況下,主動去檢測綁定的數據源,比對下是否有發生變化來判斷是否需要刷新視圖。

當然,以上的理解僅僅是很淺的層面,只是理清了三大框架是如何知道我們數據更新的時機這個問題。

對於三大框架來說,他們的視圖刷新並非是這么簡單的實現。比如說:

對於 vue,當它監聽到某個數據源發生變化了,但它並不會立馬去刷新視圖,而是將相關的信息先記錄起來,等待一個固定頻率的下個幀信號,在這期間發生變化的數據源都會被記錄起來。直到信號來的時候,再一起去處理這次的視圖刷新。

這也是為什么一些 vue 的書中或者項目中,會有要求說某些代碼需要放在下一個 tick 中去執行,因為數據源剛發生變化時,頁面不一定就更新了。

原理跟 Android 的屏幕刷新機制很像,就都是以一個固定頻率來刷新頁面,在每個幀信號之間,只是收集發生變化的視圖,或者說,只更新虛擬 DOM,並不會去更新真實的頁面。直到幀信號到的時候,再一次性的批處理地刷新頁面。

對於 Angular 來說,雖然它是不斷輪詢的方式來檢測數據源是否發生變化,但並不意味着時時刻刻都在輪詢檢測,而只在一些有可能導致視圖更新的場景下才會去檢測。比如說,滑動頁面,比如說 settimeout 事件。

這也是為什么在 Angular 項目中,經常會看到一些 settimeout(..., 0) 這樣的操作。

以上,個人的理解,如有錯誤,歡迎指點一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM