高效的Mobx模式(Part 1 - 構建可觀察數據)

原由

很早以前看到的一篇關於mobx的文章,以前記得是有人翻譯過的,可是怎麼找都找不到,故花了點時間經過本身那半桶水的英文水平,加上Google翻譯一下,對於初學者,以及mobx的開發者提供些許幫助。javascript

這裏針對已經瞭解mobx,且有過一些簡單的開發的同窗,其中對文章有一些刪減,還有翻譯的不對的地方歡迎你們指出。java

高效的Mobx模式 - (Part 1)

MobX提供了一種簡單而強大的方法來管理客戶端狀態。 它使用一種稱爲(TFRP-Transparent Functional Reactive Programming)的技術,其中若是任何相關值發生變化,它會自動計算派生值。 也就是經過設置跟蹤值更改的依賴關係圖來完成的。redux

MobX致使思惟方式的轉變(For the better),並改變您的心理模型圍繞管理客戶端狀態。segmentfault

Part 1 - 構建可觀察者

當咱們使用Mobx時,創建客戶端狀態模型是第一步, 這是最有可能被客戶端上呈現你的域模型的直接體現。實際上客戶端狀態也就是咱們一般說的Store,瞭解redux的對此都很熟悉,雖然你只有一個Store,可是它是由多個子Store組件的,每個子Store用來處理應用程序的各類功能。數組

最簡單的入門方法是註釋Store的屬性,這些屬性將隨着@observable而不斷變化。 請注意,我使用的是裝飾器語法,但使用簡單的ES5函數包裝器能夠實現相同的功能。函數

import { observable } from 'mobx'
class MyStore {
    @observable name
    @observable description
    @observable author

    @observable photos = [] 
}

修剪可觀察屬性

經過將對象標記爲@observable,您將自動觀察其全部嵌套屬性。 如今這多是你想要的東西,但不少時候它更能限制可觀察性。 你可使用一些MobX修飾符來作到這一點:性能

asReference

當某些屬性永遠不會改變值時,這是很是有用的。 請注意,若是您確實更改了引用自己,它將觸發更改。ui

let address = new Address();
let contact = observable({
    person: new Person(),
    address: asReference(address)
});

address.city = 'New York'; // 不會觸發通知任何

// 將觸發通知,由於這是屬性引用更改
contact.address = new Address();

在上面的示例中,address屬性將不可觀察。 若是您更改地址詳細信息,則不會收到通知。 可是,若是您更改地址引用自己,您將收到通知。this

一個有趣的消息是一個可觀察對象的屬性,其值具備原型(類實例)將自動使用asReference()註釋。 此外,這些屬性不會被進一步遞歸。
spa


asFlat

這比asReference略寬一些。 asFlat容許屬性自己可觀察,但不容許其任何子節點。 典型用法適用於您只想觀察數組實例而不是其項目的數組。 請注意,對於數組,length屬性仍然是可觀察的,由於它在數組實例上。 可是,對子屬性的任何更改都不會被觀察到。

首先建立 @observable全部內容,而後應用 asReferenceasFlat修飾符來修剪可觀察屬性。

當你深刻實現應用程序的各類功能時,你會發現這種修剪的好處。且當你開始時可能並不明顯,這徹底很正常。當你識別出不須要深度可觀察性的屬性時,請確保從新檢查你的Store, 它能夠對您的應用程序的性能產生積極影響。

import {observable} from 'mobx';

class AlbumStore {
    @observable name;
    
    // 這裏不須要觀察
    @observable createdDate = asReference(new Date()); 
    
    @observable description;
    @observable author;
    
    // 只觀察照片數組,而不是單獨的照片
    @observable photos = asFlat([]); 
}


擴展可觀察屬性

和修剪可觀察屬性相反,你能夠擴展對象上可觀察性的範圍/行爲,而不是刪除可觀察性。 這裏有三個能夠控制它的修飾符:

asStructure

這會修改將新值分配給observable時完成相等性檢查的方式。 默認狀況下,僅將引用更改視爲更改。 若是您但願基於內部結構進行比較,則可使用此修飾符。 這主要是針對值類型(也稱爲結構),只有在它們的值匹配時才相等。以下圖:

const { asStructure, observable } = require('mobx');

let address1 = {
    zip: 12345,
    city: 'New York'
};

let address2 = {
    zip: 12345,
    city: 'New York'
};

let contact = {
    address: observable(address1)
};

// 將被視爲一種變化,由於它是一個新的引用
contact.address = address2;

// 使用 asStructure() 修飾
let contact2 = {
    address: observable(asStructure(address1)) 
};

// 不會被視爲一種變化,由於它具備相同的價值
contact.address = address2;


asMap

默認狀況下,將對象標記爲可觀察對象時,它只能跟蹤最初在對象上定義的屬性。 若是添加新屬性,則不會跟蹤這些屬性。 使用asMap,您甚至可使新添加的屬性可觀察。 在內部,MobX將建立一個相似ES6的Map,它具備與原生Map相似的API。

除了使用此修飾符,您還能夠經過從常規可觀察對象開始來實現相似的效果。 而後,您可使用extendObservable()API添加更多可觀察的屬性。 當您想要延遲添加可觀察屬性時,此API很是有用。


computed

這是一個如此強大的概念,其重要性沒法獲得足夠的重視。 計算屬性不是域的真實屬性,而是使用實際屬性派生(也稱爲計算)。 一個典型的例子是person實例的fullName屬性。 它派生自firstName和lastName屬性。 經過建立簡單的計算屬性,您能夠簡化域邏輯。 例如,您能夠只建立一個計算的hasLastName屬性,而不是檢查一我的是否在任何地方都有lastName

class Person {
    @observable firstName;
    @observable lastName;

    @computed get fullName() {
        return `${this.firstName}, ${this.lastName}`;
    }

    @computed get hasLastName() {
        return !!this.lastName;
    }
}

構建可觀察樹是使用MobX的一個重要方面,這使MobX開始跟蹤您的store中有趣且值得改變的部分!

特此聲明: 在新版本4.0以上, asFlatasStructureasReference以及 asMap等其餘API已經被棄用,具體事宜需參閱更新文檔。
相關文章
相關標籤/搜索