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

寫文章不容易,點個讚唄兄弟
專一 Vue 源碼分享,文章分爲白話版和 源碼版,白話版助於理解工做原理,源碼版助於瞭解內部詳情,讓咱們一塊兒學習吧
研究基於 Vue版本 【2.5.17】

若是你以爲排版難看,請點擊 下面連接 或者 拉到 下面關注公衆號也能夠吧數組

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

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

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

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

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

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


響應式系統

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

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

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

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

一、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 內部打印一份數據供你們簡單瞭解便可

v2-8d6ac9507c5ac9f738b2ef5fc7b1482e_hd.jpg

能夠看到,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 可用於 進行視圖更新

最後

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

v2-89a67da8acf79ae1b5bae235bd846040_b.jpg

v2-b5b7d1e5889a1ab479f46caf52a28d8e_b.jpg

相關文章
相關標籤/搜索