【Vue原理】響應式原理 - 白話版




【Vue原理】響應式原理 - 白話版


本文打算 白話文的形式講解 Vue 的響應式系統原理,儘可能不涉及源碼。
數組

只闡述工做流程,不想內容過多過於繁雜,致使你們會沒有什麼閱讀的興趣。bash

因此我從此打算把每個內容分紅 白話版和 源碼版。函數

白話版,就是讓你們不用花費太多腦力,不用消耗太多時間,就能輕鬆地看完並大體瞭解內容。學習

有時間精力的人能夠閱讀源碼版 ,而後本身參考源碼,來進行研究學習。有什麼錯誤的地方,感謝你們可以指出ui





響應式系統

咱們都知道,只要在 Vue 實例中聲明過的數據,那麼這個數據就是響應式的。spa

什麼是響應式,也便是說,數據發生改變的時候,視圖會從新渲染,匹配更新爲最新的值。設計

也正是由於這個系統,讓咱們能夠脫離界面的束縛,只須要操做數據。code


咱們能夠問出下面三個問題cdn


一、Vue 是怎麼知道數據改變?對象

二、Vue 在數據改變時,怎麼知道通知哪些視圖更新?

三、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,可用於實例更新


總結一下

一、data 中每一個聲明的屬性,都會有一個 專屬的依賴收集器 subs

二、當頁面使用到 某個屬性時,頁面的 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 函數時,通知視圖,視圖開始更新


簡單總結

一、Object.defineProperty - get ,用於 依賴收集

二、Object.defineProperty - set,用於 依賴更新

三、每一個 data 聲明的屬性,都擁有一個的專屬依賴收集器 subs

四、依賴收集器 subs 保存的依賴是 watcher

五、watcher 可用於 進行視圖更新


最後

哈哈,最近好多的人都說我很高產,其實個人文章就是個人筆記,我作了不少筆記,可是個人筆記樣式不堪入目,因此發文章須要排版,並且部份內容須要寫得更加詳細一些,所以須要更多的時間去驗證研究,因此有時懶得發文章。

謝謝個人每個粉絲的支持,我一直之內容高質量,排版看得舒服 爲目標,對待每一篇文章,因此很是耗時,可是我很認真。

若是發現有錯誤,說得不對的地方,很是感謝可以指出,本人會有重謝哈哈哈,很是歡迎一塊兒探討學習



相關文章
相關標籤/搜索