您當前的位置:首頁 > 歷史

高效能MobX模式(Part 1)

作者:由 大寶哥 發表于 歷史時間:2016-11-11

原文地址

// Mobx 3已經修改API了

MobX為管理客戶端狀態(state)提供了一套簡單並且強大的方法。它使用一種稱為

Transparent Functional Reactive Programming

(TFRP)的技術。如果一個值依賴於另一個值,那麼被依賴的值變化了,也會引起這個值的改變。這是透過建立依賴關係圖,它能夠追蹤依賴。

MobX能夠降低你的心智負擔,讓你重新思考怎樣管理一個客戶端的狀態(state)

我在用了它6個月後並且用它做了多個React的專案後,發現某些模式的使用的相當頻繁。這一系列的文章我將分享我在用MobX的過程中的心得

我打算分三部分分享,在第一部分,讓我們看看 MobX的 狀態樹長什麼樣子

Part 1 - Shaping the observables

Part 2 - Reacting to changesPart 3 - A Cookbook of use cases

開始用MobX的第一步可能就是要為你的客戶端建模了。這就像領域模型對映到你的應用上。從現在開始,我們將客戶端狀態稱為Store,當我說客戶端狀態的時候,其實我說的就是Store。要是以前用過Redux的話,你看能會熟悉這個概念。儘管你只有一個Store,但這個Store可以又多個子Store共同組成,然後一起處理你應用程式的各種功能。

最簡單的辦法就是在Store的屬性前面加一個 @observable,注意了啊,我用的是語法是註解(

decorator syntax

),如果你用的是ES5的話,你也可以用obserable 函式包裝一下。

import

{

observable

}

from

‘mobx’

class

AlbumStore

{

@

observable

name

@

observable

createdDate

@

observable

description

@

observable

author

@

observable

photos

=

[];

}

修剪observable

如果你在一個物件前面加了

@

observable

, 那麼他裡面所有巢狀的子屬性也會被置於

observe

下。上面這種情況是你大多數時候想要的結果,但是有的時候,你想只讓一部分

observe

下。你可以用 MobX modifiers做到這一點。

asReference()

如果是你知道一個物件,他裡面的值萬年不變而且永遠不會改變。這個方法非常有用了。注意了哈,如果我改變這個物件自身的引用,他還是會觸發改變通知的。比如說

let

address

=

new

Address

();

let

contact

=

observable

({

person

new

Person

(),

address

asReference

address

});

address

city

=

‘New York’

// No notifications won`t be fired

// Notifications will be fired as this is a reference change

contact

address

=

new

Address

();

上面這個例子,這個

address

裡面的屬性是不具備

observable

的。所以我改了裡面的內容,我是收不到改變通知的。然而我們改變

address

的引用,我們照舊會拿到改變通知

asFlat()

這個要比

asReference()

稍微寬鬆些,

asFlat

允許將自己的第一層子屬性置於

observe

下,這個最典型的用法就是用在陣列上,我只想觀察數組裡每一子項移入移除的變化,而不想知道每一子項內部的屬性如何變化的。在這種情況下,陣列的

length

改變我能不能觀察到啊?當然可以。

高效能MobX模式(Part 1)

高效能MobX模式(Part 1)

小提示:一個物件我們必須先是

observable

的,我們才能對他子屬性用

asReference

或者

asFlat

進行修剪。

如果你對你的

store

用深刻的理解,能夠確定哪些屬性不要深入

observable。

那麼這將對你的應用程式的效能提升有非常重要的意思

import

{

observable

}

from

‘mobx’

class

AlbumStore

{

@

observable

name

// No need to observe here

@

observable

createdDate

=

asReference

new

Date

());

@

observable

description

@

observable

author

// Only observing the photos array, not the individual photos

@

observable

photos

=

asFlat

([]);

}

擴充套件observable的能力

上面我們一直在說如何剪裁一個物件的

observable

的能力,那麼下面我們聊一聊如何擴充套件一個物件的

observable

的能力。

asStructure()

高效能MobX模式(Part 1)

高效能MobX模式(Part 1)

預設情況下只有引用的變化才會被認為是發生了變化。但是你希望你覺得內部結構的值變了才認為是發生了變話,那麼你可以用用它。他是建立在 type 和 value 基礎上的,他會比對type和value,如果他倆均沒發生改變,就認為它沒變

const

{

asStructure

observable

reaction

}

=

require

‘mobx’

let

address1

=

{

zip

12345

city

‘New York’

}

let

address2

=

{

zip

12345

city

‘New York’

}

let

contact

=

observable

({

address

address1

})

// Will be considered as a change, since its a new reference

contact

address

=

address2

// With asStructure() annotation

let

contact

=

observable

({

address

asStructure

address1

})

// Will NOT be considered as a change, since its the same value

contact

address

=

address2

asMap()

預設情況下,當你標記一個物件作為可觀察到的,它只能跟蹤到這個物件下面最開始定義的那些屬性。如果你在這個物件下再加一個新的屬性,那麼這個屬性是不會被追蹤到的。用

asMap

()就可以解決這個問題。

computed()

這個概念自己超級重要,怎麼強調都不過分。一個computed屬性並不是你領域模型裡面的屬性,而是根據你的領域模型計算出來的屬性。最典型的例子就是一個person例項的fullName是根據person例項的lastName和

firstName

計算出來的。它能夠幫助你減化你的領域模型的邏輯推理。舉個簡單的例子,你不必在用到檢查是否有lastName的地方都寫檢查邏輯,你只需要寫一個computed

hasLastName

的屬性就好了。程式碼如下

class

Person

{

@

observable

firstName

@

observable

lastName

@

computed

get

fullName

()

{

return

`

${

this

firstName

}

${

this

lastName

}

`

}

@

computed

get

hasLastName

()

{

return

!!

this

lastName

}

}

高效能MobX模式(Part 1)

高效能MobX模式(Part 1)

怎麼理解這張圖呢?帶加號的那兩個,是透過asMap新加的兩個屬性,另一個是computed的屬性。他們都被置於可觀察下

未完待續

在第二部分,我們來聊聊用當那些被置於可觀察下的值變化時,我們如何使用

@action。

來處理副作用

標簽: observable  屬性  address  mobx  Store