1. 程式人生 > 實用技巧 >vue-響應式原理

vue-響應式原理

發現一篇以白話文的形式講解 Vue 的響應式系統原理的文章,覺得不錯~ 響應式系統 我們都知道,只要在 Vue 例項中宣告過的資料,那麼這個資料就是響應式的。 什麼是響應式,也即是說,資料發生改變的時候,檢視會重新渲染,匹配更新為最新的值。 也正是因為這個系統,讓我們可以脫離介面的束縛,只需要操作資料。 我們可以問出下面三個問題 1、Vue 是怎麼知道資料改變? 2、Vue 在資料改變時,怎麼知道通知哪些檢視更新? 3、Vue 在資料改變時,檢視怎麼知道什麼時候更新? 問題的謎底將在下面一一解開 現在,我將會講解三個重要的概念 Object.defineProperty,依賴收集,依賴更新
Object.defineProperty 這個方法,是 Vue 響應式系統的精髓,骨髓,腦髓 使用 Object.defineProperty 可以為物件中的每一個屬性,設定 get 和 set 方法 Object.defineProperty 可以為屬性設定很多特性,例如 configurable,enumerable,但是現在不過多解釋,重點只放在 get 和 set 那麼 get 和 set 方法有什麼用? get 值是一個函式,當屬性被訪問時,會觸發 get 函式 set 值同樣是一個函式,當屬性被賦值時,會觸發 set 函式 舉個例子
var obj={    
    name:
"張三" } Object.defineProperty(obj,"name",{ get(){ console.log("get 被觸發") }, set(val){ console.log("set 被觸發") } })
當我訪問 obj.name 時,會列印 ' get 被觸發 ' 當我為 obj.name 賦值時,obj.name = 5,會列印 ' set 被觸發 ' 這便可以回答了我開篇的第一個問題 Vue 是怎麼知道資料改變的呢? 恩,Vue 在 屬性的 set 方法中做了手腳,因而當資料改變時,觸發 屬性的 set 方法,Vue 就能知道資料有改變
依賴收集 簡單地說 data 中的宣告的每個屬性,都擁有一個數組,儲存著 誰依賴(使用)了 它 舉個例子
new Vue({    
    data(){        
        return {            
            name:"張三"        
        }    
    }
})
然後 頁面A 引用了name <div>{{name}}</div> 此時,name 把 頁面 A 存在它的後宮中(這個頁面依賴我) 為什麼呢? 因為它知道誰依賴它之後,它就可以在發生改變的時候,通知 依賴它的頁面,從而讓頁面完成更新 TIP 實際上,會依賴 name 的地方,不只是頁面,還會有 computed,watch.... 等等,但是這裡我們全部使用頁面一詞替代 這就是依賴收集,把 依賴了我(使用了我的東西),統統儲存起來。 可是,儲存在哪裡,具體儲存的是什麼東西,我們這裡暫時不深入,因為這是白話文。 我按上面的例子,從Vue 內部列印一份資料供大家簡單瞭解即可 可以看到,name 屬性,使用了 一個 dep 儲存了 頁面A 這個依賴,而儲存的實際上是 頁面A的 Watcher。 TIP 簡單說一下,watcher 是什麼,每個 Vue 例項都會擁有一個專屬的 watcher,可用於例項更新 總結一下 1、data 中每個宣告的屬性,都會有一個 專屬的依賴收集器 subs 2、當頁面使用到 某個屬性時,頁面的 watcher 就會被 放到 依賴收集器 subs 中 資料 是在什麼時候進行 收集依賴 的呢? 答案是,ObjectdefineProperty - get 當 頁面 A 讀取了 name 時,會觸發 name 的 get 函式,此時,name 就會儲存 頁面A 的 watcher 啦! 這便可以回答了我開篇的第二個問題 Vue 在資料改變時,怎麼知道通知哪些檢視更新? 恩,通知那些存在 依賴收集器中的 檢視 依賴更新 依賴更新,就是,通知所有的依賴進行更新 經過上面的講解,我們都知道,每個屬性都會儲存有一個 依賴收集器subs 而這個 依賴收集器,是用來在 資料變化時,通知更新的 資料 是在 什麼時候進行 依賴更新 的呢? 答案是,Object.defineProperty - set 以上面的 Vue 例項 為例 當 name 改變的時候,name 會遍歷自己的 依賴收集器 subs,逐個通知 watcher,讓 watcher 完成更新 這裡 name 會通知 頁面A,頁面A 重新讀取新的 name ,然後完成渲染 這便可以回答了我開篇的第二個問題 Vue 在資料改變時,檢視怎麼知道什麼時候更新? 恩,在資料變化觸發 set 函式時,通知檢視,檢視開始更新 簡單總結 1、Object.defineProperty - get ,用於 依賴收集 2、Object.defineProperty - set,用於 依賴更新 3、每個 data 宣告的屬性,都擁有一個的專屬依賴收集器 subs 4、依賴收集器 subs 儲存的依賴是 watcher 5、watcher 可用於 進行檢視更新