Mobx 源碼分析 - 第一階段彙總

當咱們寫 age = observable.box(12) 的時候,寫 @observable age = 12 的時候,寫 age = observable(12) 的時候,mobx 作了什麼?不知道有多少人仔細研究過,沒研究也沒關係,這篇文章就是帶你去了解,mobx 具體作了什麼?api

api/observable.ts 文件

observable.box

observable 上綁定了許多屬性,好比經常使用的 boxmaparray。當咱們調用 observable.box 的時候,mobx 會首先判斷當前調用方式,若是當前的調用方式會 decorator 調用,則直接報錯。函數

if (arguments.length > 2) incorrectlyUsedAsDecorator("box")
複製代碼

爲何 mobx 能夠經過參數個數就能判斷出來當前是否爲 decorator 調用?那是由於若是經過裝飾器調用,會往函數內傳入 3 個參數,因此這邊經過判斷參數個數就能夠肯定當前是否爲 decorator 調用。源碼分析

相信你們都知道 box 方法還有第二個參數 (不單單只是 box 有),這個參數的做用主要用以判斷用哪個 enhancername 的值。post

最後返回 ObservableValue 實例。ui

new ObservableValue(value, getEnhancerFromOptions(o), o.name, true, o.equals)
複製代碼

@observable

調用 observable 時候,等於調用 createObservablespa

const observable = createObservable
複製代碼

createObservable 接收 3 個參數,內部會對第二個參數進行判斷,若是爲 string,則調用 deepDecorator 函數。3d

observable()

若是傳入的參數爲已監聽對象,則直接返回;若是不是基本數據類型,則根據參數類型調用不一樣的包裝方法,好比對於 array 調用 observable.array。若是是 NaN,直接返回。若是是基本數據類型,提醒用戶使用 observable.box 方法。code


咱們已經知道 mobx 對於咱們的代碼會作兩件不一樣的事,一種調用 deepDecorator 函數,一種實例化 ObservableValue對象

注意,這裏咱們只針對於傳入的值爲 number 類型討論,不一樣類型有不一樣的實現方式繼承

observable.box

實例化 ObservableValueObservableValue 類繼承 Atom 類,ObservableValue 內部重寫了 setget 方法。

當訪問實例時,會向全局發出 reportObserved 事件,並把當前實例存到 derivation.newObserving 中,以便數據發生更改,通知 derivation。在這裏,實例爲被觀察者,derivation 爲觀察者。

修改實例值時,會開啓事務處理,並向全部的觀察者推送這次事件,推送完成後結束事務處理。

究竟 mobx 是如何更新依賴關係?咱們以 autorun 舉例。

autorun(()=>{
    console.log(age.get())
})
複製代碼

當咱們調用 autorun 時候,會在全局狀態中增長當前實例,也就是當前的 derivationautorun 參數執行時,會把 age 的值,也就是 ObservableValue 實例,推入到當前的 derivation 屬性中,derivation 會用 diffValue 來刷新當前依賴關係,保持依賴最新。

@observable

調用 createDecoratorForEnhancer 返回值,在原型上添加 __mobxDecorators 對象,此對象的每個屬性 ( 比方說 @observable age,這裏面的屬性就是 age ) 都會存放一些關鍵信息,並劫持屬性的 getset 方法。

target.__mobxDecorators[prop] = {
    prop,
    propertyCreator,
    descriptor,
    decoratorTarget: target,
    decoratorArguments
}
複製代碼

當訪問屬性,會在原型上添加 __mobxDidRunLazyInitializers$mobx$mobx 內存放 ObservableObjectAdministration 實例,並在 $mobx.values 對應的每個屬性存放 ObservableValue 實例。

const observable = (adm.values[propName] = new ObservableValue(
    newValue,
    enhancer,
    `${adm.name}.${propName}`,
    false
))
複製代碼

並對於屬性的訪問和讀取會再次劫持,每當訪問,都會調用原型上 $mobxreadwrite 方法。readwrite 方法所作的事與 observable.box 內部 getset 作的事情同樣。

文章列表

相關文章
相關標籤/搜索