本文介紹了MobX中一些簡(jiǎn)單的概念及React Native中的應(yīng)用。
本文首發(fā):http://yuweiguocn.github.io/
《絕句》
兩個(gè)黃鸝鳴翠柳,一行白鷺上青天。
窗含西嶺千秋雪,門泊東吳萬里船。
—唐,杜甫
MobX簡(jiǎn)介
MobX 通過透明的函數(shù)響應(yīng)式編程(transparently applying functional reactive programming - TFRP)使得狀態(tài)管理變得簡(jiǎn)單和可擴(kuò)展。MobX背后的哲學(xué)很簡(jiǎn)單:
任何源自應(yīng)用狀態(tài)的東西都應(yīng)該自動(dòng)地獲得。
其中包括UI、數(shù)據(jù)序列化、服務(wù)器通訊,等等。

React 和 MobX 是一對(duì)強(qiáng)力組合。React 通過提供機(jī)制把應(yīng)用狀態(tài)轉(zhuǎn)換為可渲染組件樹并對(duì)其進(jìn)行渲染。而MobX提供機(jī)制來存儲(chǔ)和更新應(yīng)用狀態(tài)供 React 使用。
對(duì)于應(yīng)用開發(fā)中的常見問題,React 和 MobX 都提供了最優(yōu)和獨(dú)特的解決方案。React 提供了優(yōu)化UI渲染的機(jī)制, 這種機(jī)制就是通過使用虛擬DOM來減少昂貴的DOM變化的數(shù)量。MobX 提供了優(yōu)化應(yīng)用狀態(tài)與 React 組件同步的機(jī)制,這種機(jī)制就是使用響應(yīng)式虛擬依賴狀態(tài)圖表,它只有在真正需要的時(shí)候才更新并且永遠(yuǎn)保持是最新的。
安裝MobX
安裝MobX:
npm install mobx --save
npm install mobx-react --save
MobX推薦使用ES7的decorator語法,以實(shí)現(xiàn)最精煉的表達(dá)。安裝裝飾器支持:
npm i --save-dev babel-plugin-transform-decorators-legacy
然后在 .babelrc 文件中啟用它:
.babelrc:
{
"plugins": ["transform-decorators-legacy"]
}
裝飾器說明
我們先來學(xué)習(xí)下幾個(gè)簡(jiǎn)單的裝飾器,然后通過一個(gè)實(shí)例來說明怎樣使用。
| 裝飾器 | 說明 |
|---|---|
| @observable | 用于將實(shí)例字段和屬性 getter 變成可觀察的。 |
| @action | 用于裝飾可觀察變量的狀態(tài)的更新。在嚴(yán)格模式下,對(duì)于可觀察變量的狀態(tài)的更新必須使用此裝飾器。 |
| @observer | 用于將 React 組件轉(zhuǎn)變成響應(yīng)式組件。 |
嚴(yán)格模式
用法: useStrict(boolean)。 全局性 地啟用/禁用嚴(yán)格模式。建議啟用嚴(yán)格模式,在嚴(yán)格模式下,所有修改可觀察變量的地方必須(放在action中或)添加 @action 裝飾器。下面我們?cè)趇ndex.js文件中全局啟用嚴(yán)格模式:
index.js
import { AppRegistry } from 'react-native';
import { useStrict } from 'mobx'
import App from './App';
useStrict(true);
AppRegistry.registerComponent('RNTest', () => App);
MobX使用
接下來我們使用MobX中的特性改造在上一篇文章中實(shí)現(xiàn)的功能,首先新建一個(gè)store類:
/App/appCountStore.js
import {action, observable} from "mobx";
export default class AppCountStore{
@observable count = 0;
@action addCount = () => {
this.count++;
};
}
在上面的代碼中,我們使用 @observable 定義count為可觀察變量,由于在addCount方法中更新count變量的值,所以需要添加 @action 修飾。
在上一篇文章中我們介紹了Component和PureComponent之間的區(qū)別,@observer 用同樣的方式實(shí)現(xiàn)了 shouldComponentUpdate方法,所以我們使用Component即可。首先引入store類并實(shí)例化,在需要的地方引用store中的屬性,然后使用 @observer 修飾組件類。
/App/index.js
import React, {Component} from 'react';
import {StyleSheet, Text, Button, View} from 'react-native';
import {observer} from 'mobx-react';
import AppCountStore from './appCountStore';
import CustomToast from './customToast';
const appCount=new AppCountStore();
@observer
class CountText extends Component {
render() {
return (<Text>{appCount.count}</Text>);
}
}
@observer
export default class App extends Component {
pressButton = () => {
appCount.addCount();
CustomToast.show("count is "+appCount.count,CustomToast.SHORT);
};
render() {
console.log("render");
return (
<View style={styles.container}>
<Button onPress={this.pressButton}
title="Click Me"
color="#841584"/>
<CountText style={styles.countText} />
</View>
);
}
}
...

圖 運(yùn)行效果
關(guān)于 @observer 的使用:如果組件中用到了 @observable 可觀察變量,那么組件就應(yīng)該使用 @observer 修飾。MobX作者mweststrate推薦對(duì)父組件和子組件都使用 @observer。添加 @observer 對(duì)性能的影響可以忽略不計(jì),不需要擔(dān)心由此引發(fā)的性能問題,事實(shí)上作者在自己的項(xiàng)目中對(duì)所有的組件都是使用 @observer 修飾,也沒有性能問題。詳見:Do child components need @observer?
查看完整源碼:https://github.com/yuweiguocn/RNTest
查看React Native學(xué)習(xí)筆記相關(guān)文章。