react-mobx-2


observable

observable(value)
@observable classProperty = value

// 若是 value 是ES6 Map的實例: 會返回一個新的 Observable Map。不僅關注某個特定entry的更改,並且對更改添加或刪除其餘entry時也作出反應。

// 若是 value 是數組,會返回一個 Observable Array。

// 若是 value 是沒有原型的對象或它的原型是 Object.prototype,那麼對象會被克隆而且全部的屬性都會被轉換成可觀察的。

// 若是 value 是有原型的對象,JavaSript 原始數據類型或者函數,值不會發生變化。若是你須要 Boxed Observable:

1, 顯式地調用 observable.box(value) 
// observable.box(value, options?),
// 使用 get() 方法能夠獲得盒子中的當前value,而使用 set() 方法能夠更新value
// 使用 {deep: false} 選項會禁用新值被observable。
 
  
2, 在類定義時使用 @observable , // 是 的語法糖 3, 調用 decorate()
4, 在類中使用 extendObservable() 來引入屬性extendObservable(this, { property: value })
// 要想使用 @observable 裝飾器,首先要確保編譯器(babel 或者 typescript)中 裝飾器是啓用的。

// 默認狀況下將一個數據結構轉換成可觀察的是有感染性的,這意味着 observable 被自動應用於數據結構包含的任何值,或者未來會被該數據結構包含的值。這個行爲能夠經過使用 裝飾器 來更改
// 爲提供的對象建立一個克隆並將其全部的屬性轉換成 observable
// 使用 {deep: false} 選項時只有屬性會轉換成 observable 引用,而值不會改變(這也適用於未來分配的任何值)。
observable.object(value, decorators?, options?)

observable.array(value, options?)
// 基於提供的值來建立一個新的 observable 數組。

observable.map(value, options?)
// 基於提供的值來建立一個新的 observable 映射 建立動態的鍵集合而且須要能觀察到鍵的添加和移除,能夠自由使用任何鍵而無需侷限於字符串。
extendObservable(target, properties, decorators?, options?)
// extendObservable 加強了現有的對象,不像 observable.object 是建立一個新對象

// 若是新的屬性不該該具有感染性,extendObservable(target, props, decorators?, {deep: false})


裝飾器(Decorators)

// 若是沒有傳入裝飾器,默認爲對任意鍵值對使用 observable.deep,對 getters 使用 computed 。typescript

observable.deep: 
// 全部 observable 都使用的默認的裝飾器。它能夠把任何指定的、非原始數據類型的、非 observable 的值轉換成 observable。

observable.ref: 
// 禁用自動的 observable 轉換,只是建立一個 observable 引用。

observable.shallow: 
// 只能與集合組合使用。 將任何分配的集合轉換爲淺 observable (而不是深 observable)的集合。 換句話說, 集合中的值將不會自動變爲 observable。

computed: 
// 建立一個衍生屬性

:
// 與  相同,可是隻有當視圖產生的值與以前的值結構上有不一樣時,才通知它的觀察者
action: // 建立一個動做

:
// 建立一個動做, 並將  綁定到了實例

:
// 就像 , 但會忽略結構上等於當前值的新值

computed.structcomputedaction.boundthisobservable.structref
// @decorator 語法應用裝飾器

import {observable, action} from 'mobx';

class TaskStore {
    @observable.shallow tasks = []
    @action addTask(task) { /* ... */ }
}
// decorate() 傳入屬性裝飾器

import {observable, action} from 'mobx';

const taskStore = observable({
    tasks: [],
    addTask(task) { /* ... */ }
}, { tasks: observable.shallow, addTask: action })
// 使用 decorate 時,全部字段都應該指定 (畢竟,類裏的非 observable 字段可能會更多)

class Person {
    name = "John"
    age = 42
    showAge = false

    get labelText() {
        return this.showAge ? `${this.name} (age: ${this.age})` : this.name;
    }

    setAge(age) {
        this.age = age;
    }
}

decorate(Person, {
    name: observable,
    age: observable,
    showAge: observable,
    labelText: computed,
    setAge: action
})
// 想要在單個屬性上應用多個裝飾器的話,能夠傳入一個裝飾器數組。多個裝飾器應用的順序是從右至左。

import { decorate, observable } from 'mobx'
import { serializable, primitive } from 'serializr'
import persist from 'mobx-persist'

class Todo {
    id = Math.random();
    title = '';
    finished = false;
}

decorate(Todo, {
    title: [serializable(primitive), persist('object'), observable],
    finished: [serializable(primitive), observable]
})

 

Computed values(計算值)

// @computed

import {observable, computed} from "mobx";

class OrderLine {
    @observable price = 0;
    @observable amount = 1;

    constructor(price) {
        this.price = price;
    }

    @computed get total() {
        return this.price * this.amount;
    }
}
// 使用 decorate 引入

import {decorate, observable, computed} from "mobx";

class OrderLine {
    price = 0;
    amount = 1;
    constructor(price) {
        this.price = price;
    }

    get total() {
        return this.price * this.amount;
    }
}
decorate(OrderLine, {
    price: observable,
    amount: observable,
    total: computed
})
// observable.object 和 extendObservable 都會自動將 getter 屬性推導成計算屬性

const orderLine = observable.object({
    price: 0,
    amount: 1,
    get total() {
        return this.price * this.amount
    }
})
// 計算值的 setter
// setters 不能用來直接改變計算屬性的值,能夠用來做「逆向」衍生。

const orderLine = observable.object({
    price: 0,
    amount: 1,
    get total() {
        return this.price * this.amount
    },
    set total(total) {
        // 從 total 中推導出 price
        this.price = total / this.amount 
    }
})    
// 注意: 永遠在 getter 以後 定義 setter,一些 TypeScript 版本會知道聲明瞭兩個具備相同名稱的屬性

class Foo {
    @observable length = 2;
    @computed get squared() {
        return this.length * this.length;
    }
    set squared(value) { 
        this.length = Math.sqrt(value);
    }
}
// computed 還能夠直接當作函數來調用, 可用於傳遞在box中計算值

import {observable, computed} from "mobx";
var name = observable.box("John");

var upperCaseName = computed(() =>
    name.get().toUpperCase() // 使用  來獲取計算的當前值
);
//  來觀察值的改變
var disposer = upperCaseName.observe(change => console.log(change.newValue)); name.set("Dave"); // 輸出: 'DAVE'.get().observe(callback)
computed 接收的第二個選項參數對象選項

name: 字符串, 在 spy 和 MobX 開發者工具中使用的調試名稱

context: 在提供的表達式中使用的 this

set: 要使用的setter函數。 沒有 setter 的話沒法爲計算值分配新值。 若是傳遞給 computed 的第二個參數是一個函數,那麼就把會這個函數做爲 setter

equals: 默認值是 comparer.default 。它充當比較前一個值和後一個值的比較函數。
MobX 提供了三個內置 comparer (比較器) 
comparer.identity: 使用恆等 (===) 運算符來斷定兩個值是否相同。
comparer.default: 等同於 comparer.identity,但還認爲 NaN 等於 NaN 
comparer.structural: 執行深層結構比較以肯定兩個值是否相同。

requiresReaction: 對於很是關鍵的計算值,推薦設置成 true 。避免沒有跟蹤該值致使計算結果丟失。

keepAlive:  有無觀察者均保持計算。這很容易致使內存泄漏,由於它會致使此計算值使用的每一個 observable ,並將計算值保存在內存中!
// computed 錯誤處理

const x = observable.box(3)
const y = observable.box(1)
const divided = computed(() => {
    if (y.get() === 0)
        throw new Error("Division by zero") return x.get() / y.get()
})

divided.get() // 返回 3

y.set(0) // OK
divided.get() // 報錯: Division by zero
divided.get() // 報錯: Division by zero

y.set(2)
divided.get() // 已恢復; 返回 1.5

 

Actions(動做)

// 建議在任何更改 observable 或者有反作用的函數上使用動做
// 動做還能提供很是有用的調試信息

action(fn)
action(name, fn)
@action classMethod() {}
@action(name) classMethod () {}
@action boundClassMethod = (args) => { body }
@action(name) boundClassMethod = (args) => { body }
@action.bound classMethod() {}

// 它接收一個函數並返回具備一樣簽名的函數
// 用 transaction、untracked 和 allowStateChanges 包裹起來
// 默認是使用transaction, 動做會分批處理變化並只在(最外層的)動做完成後通知計算值和反應
// @action 裝飾器 不支持使用 setters
//  綁定的動做
//  action.bound 能夠用來自動地將動做綁定到目標對象。 
//  注意,與 action 不一樣的是,(@)action.bound 不須要一個name參數,名稱將始終基於動做綁定的屬性。

class Ticker {
    @observable tick = 0 @action.bound
    increment() {
        this.tick++ // 'this' 永遠都是正確的
    }
}

const ticker = new Ticker()
setInterval(ticker.increment, 1000)
runInAction(name?, thunk) 

// 工具函數,它接收代碼塊並在(異步的)動做中執行。這對於即時建立和執行動做很是有用
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息