推薦版本: "mobx-react": "4.1.0", "mobx": "^2.7.0 || ^3.0.0"react
能夠任何數據結構來存儲狀態,如對象、數組、類,打上mobx的標記會變爲可觀察。git
import { observable } from 'mobx'; var appStore = observable({ timer: 0; });
mobx 以最小限度更新視圖,任何函數均可以成爲響應式視圖觀察自身數據。 github
import {observer} from 'mobx-react'; @observer class TimerView extends React.Component { render() { return ( <button onClick={this.onReset.bind(this)}> Seconds passed: {this.props.appState.timer} </button> ); } onReset() { this.props.appState.resetTimer(); } }; ReactDOM.render(<TimerView appState={appStore} />, document.body);
mobx會用簡單直觀的方式更改狀態,使用action(能夠配置Mobx強制使用action更新)或者直接修改web
狀態是驅動應用的數據。像待辦事務列表的特定狀態,還有像當前已選元素的視圖狀態。
狀態就像有數據的 Excel表格。算法
什麼是衍生, 源自狀態而且不會再有進一步的相互做用的東西就是衍生。 express
使用純函數從當前可觀察狀態中衍生出的值。 編程
是當 State 改變時須要自動發生的反作用。。須要有一個橋樑連接 函數式編程 和 響應式編程
初次使用mobx會常用reactions,可是推薦使用computed,回到表格的概念,公式是計算值的衍生。 redux
動做 任意一段能夠改變狀態的代碼。 用戶操做,後端數據推送,預約事件等。
動做 相似在表格單元格中輸入一個新值。 mobx中能夠顯示的定義動做,@action . 後端
mobx支持單向的數據流,動做來改變狀態,從而 狀態State 的改變會更新受影響的視圖。
action ---> state ---> view
當 State 改變時,全部衍生都會進行原子級自動更新 所以不可能觀察到中間值
所有的 衍生 默認都是同步更新 所以在動做以後,能夠安全的檢查計算值
計算值 是延遲更新的。 任何不在使用狀態的計算值都不會更新,直到須要時會進行 反作用(IO),不使用時會自動垃圾回收
計算值 不該該去改變狀態,應該是一個純潔的反作用。 api
主要api: Computed 、 observable 、 reactions 、 actions
observable(value); @observable property = value;
Observable 觀察的值能夠是基本類型、引用類型、普通對象、類實例、數組和映射。
主要類型轉換規則,或者經過裝飾器微調(修飾class,函數)
可用裝飾的列表是這些:
class TodoList { todos = {} get unfinishedTodoCount() { return values(this.todos).filter(todo => !todo.finished).length } addTodo() { const t = new Todo() t.title = 'Test_' + Math.random() set(this.todos, t.id, t) } } decorate(TodoList, { todos: observable, unfinishedTodoCount: computed, addTodo: action.bound }) // 對類 Observable 轉換
用法好幾種,看起來只有一些細微的差異:
Computed 自帶不少操做屬性 控制 Computed 行爲
任何用來 修改狀態 的東西
建議在任何更改 observable 或者有反作用的函數上進行 Actions修飾
flow(function* (args) {})
flow() 接收 generator 函數做爲他的惟一輸入
flow 的關鍵做用是 處理異步代碼時確保代碼被action包裝 ,由於正常的 observable state 對異步操做沒法經過 enforceActions 檢查。
神奇的flow能夠解決這個異步不跟蹤的問題
注意,異步函數必須是 generator ,並且在內部只能 yield promises
import { configure, flow } from 'mobx'; // 不容許在動做外部修改狀態 嚴格模式的意思 configure({ enforceActions: true }); class Store { @observable githubProjects = []; @observable state = "pending"; // "pending" / "done" / "error" fetchProjects = flow(function* fetchProjects() { // <- 注意*號,這是生成器函數! this.githubProjects = []; this.state = "pending"; try { const projects = yield someAsyncProcess(); // 用 yield 代替 await const filteredProjects = somePreprocessing(projects); // 異步代碼自動會被 `action` 包裝 this.state = "done"; this.githubProjects = filteredProjects; } catch (error) { this.state = "error"; } }) }
Flows 能夠撤銷,調用promise的cancel() 方法會中止異步狀態取值, 會繼續執行 finally 子句 。
計算值是能夠根據現有的狀態或其餘計算值衍生的值。
概念上來說,他們和表格中的值十分類似,好比彙總80分以上的同窗。
計算屬性 可使實際可修改的值儘量的小,計算屬性也是高度優化過的,能夠多用
聲明式的建立計算屬性,能夠在類任意的屬性上使用裝飾器
import { observable, computed } from 'mobx'; class orderline { @observable price = 10; @observable amount = 1; constructor(price) { this.price = price; } @computed get total() { return this.price * this.amount; } }
import { observable, autorun } from 'mobx'; const value = observable(0); const number = observable(100); autorun(() => { console.log(value.get()); }); value.set(1); value.set(2); number.set(101); // 0 1 2 不打印 101 yinwei number 未在autorun內部執行 number.get()/
Mobx 學習 基本寫法 * 此處聲明式的監控變量,與 ES6 的類修飾不一樣。
import { observable, action, computed, toJS } from 'mobx' import { observer } from 'mobx-react'
export default class InstanceStore { @observable value = 1
@action modifyValue(v) { this.value = v } @computed get getValue() { return this.value * 10; }
}
computed 直接獲取一個計算後的值。
若是一個值須要根據某個state計算,而且也須要被觀察則可使用 @computed autorun 相似
autorun 用於執行一些和值變化有關的操做,好比異步請求,數據處理等
computed 用於根據已有的值,計算出新的值返回一個對觀察值追蹤的結果 var ins = new InstanceStore(); console.log('value form mobx computed', toJS(ins.getValue()))
autorun 在不須要繼續使用的狀況能夠進行垃圾回收
var numbers = observable([1,2,3]);
var sum = computed(() => numbers.reduce((a, b) => a + b, 0));
var disposer = autorun(() => console.log(sum.get())); // '6'
numbers.push(4); // '10'
disposer();
numbers.push(5); // 什麼也不打印,由於disposer執行是再也不對autorun reaction
過時狀態值方式以下
var ins = new InstanceStore();
console.log(toJS(ins.value),'get value from mobx');
dispatch 修改值 var ins = new InstanceStore(); ins.modifyValue(1000);
在組件內可使用觀察者模式 @observer class routeCreate extends Component { constructor(props) { super(props); this.store = new InstanceStore(); } ... }
使用 observer 修飾組件,而且在render內部有 mobx 值的引用,組件會多一個生命週期 componentWillReact // redux 改變值的方式是經過拷貝原來的對象生成新的對象,觸發組件的componentWillReceiveProps // mobx 是以原始值的基礎上生成新的對象,以前的引用不變因此mobx 不會觸發ReceiveProps週期
異步處理
mobx 狀態值爲同步更新。
export default class InstanceStore { @observable value = 1
@action modifyValue(v) { this.value = v; setTimeout(this.valueAdd, 100); } @action.bound valueAdd(v) { this.value = v + 20; }
}
// .bound 是js執行環境語法糖 // 過多action ? 須要簡化寫法 // mobx 自身提供了一個工具函數幫助跟新對應action中的值 runInAction
export default class InstanceStore {
@observable value = 1
@action asyncModifyValue(v) { this.value = v; setTimeout(action('valueAdd', () => { this.value = v + 20 }), 100); } @action asyncModify(v) { this.value = v; setTimeout(runInAction(() => { this.value = v + 20 }), 100); }
}
// 異步action,action能夠這樣寫
@asyncAction changeValue() { this.value = 0; const data = yield Promise.resolve(1) this.value = data; }
toJS 將mobx state 序列轉換爲js可識別類型? 更新action的約束 mobx 非強制使用action改變state;若是要增強制action觸發state能夠經過 Mobx.configure({enforceActions: true}) 加限制條件,強制經過action更新,適用於大型項目 如下是遺留問題 * 1, mobx 是不是同步更新 是 * 2, mobx toJS是如何實現的 * 3,store對應單個變量,會按照類型預留數組空間,是什麼緣由 * 4,使用toJS獲取數據,須要在class名稱上面加 @observer 嗎 * 5,爲何mobx取值,是如此的簡介?,並且是支持多狀態 * 6,extendObservable 能夠按照擴展的方式 裝飾函數或class裏的對象