TypeScript 下 React + MobX 入門

why MobX贸街?

React是一個(gè)view層的解決方案沼琉,當(dāng)我們只用它來展示一些靜態(tài)數(shù)據(jù)時(shí)娃承,無需引入任何一種狀態(tài)管理庫奏夫。

當(dāng)多個(gè)有狀態(tài)組件進(jìn)行復(fù)雜的交互時(shí),如果不引入狀態(tài)管理插件历筝,只用state來實(shí)現(xiàn)酗昼,組件間的狀態(tài)交互將使代碼異常復(fù)雜,業(yè)務(wù)數(shù)據(jù)和UI交互耦合梳猪,難以閱讀麻削。

業(yè)界比較流行的狀態(tài)管理庫是redux,但是redux難以上手春弥,學(xué)習(xí)難度較高呛哟,不適合前端玩票選手。
相比之下匿沛,MobX是一個(gè)異常簡(jiǎn)單且可擴(kuò)展性高的狀態(tài)管理庫扫责,上手簡(jiǎn)單,功能強(qiáng)大逃呼,適合中小型系統(tǒng)鳖孤。

準(zhǔn)備工作

npm install mobx --save
npm install mobx-react --save
tsconfig.json中增加"experimentalDecorators": true

第一個(gè)demo

import * as React from 'react';
import * as ReactDom from 'react-dom';
import { observer } from 'mobx-react';
import { observable, useStrict, action, runInAction, computed } from 'mobx';

// 啟用mobx嚴(yán)格模式,嚴(yán)格模式下不允許直接修改@observable修飾的數(shù)據(jù)抡笼,需@action修飾的方法來修改苏揣。原則上必須用嚴(yán)格模式。
useStrict(true);
class Store {
    @observable title:string = '請(qǐng)點(diǎn)擊我推姻!';

    @action changeTitle() {
        this.title = '已經(jīng)點(diǎn)擊了平匈!';
    }
}

const store = new Store();

@observer
class TitlePanel extends React.Component<{},{}> {
    render() {
        return(<h1 onClick={() => store.changeTitle()}>{store.title}</h1>);
    }
}
ReactDom.render(<TitlePanel /> ,document.body);

這里用了三個(gè)陌生的注解,@observable修飾的數(shù)據(jù)和@observer修飾的組件綁定拾碌,當(dāng)數(shù)據(jù)發(fā)生變化時(shí)吐葱,組件對(duì)應(yīng)變化。@action修飾的方法用來改變數(shù)據(jù)校翔。非常簡(jiǎn)單易懂弟跑。

如果不用mobx,這個(gè)demo是這樣的:

class TitlePanels extends React.Component<{}, {}> {
    public state = { title: '請(qǐng)點(diǎn)擊我' };
    constructor() {
        super();
        this.onChange = this.onChange.bind(this);
    }
    onChange() {
        this.setState({ title: '已經(jīng)點(diǎn)擊了防症!' });
    }
    render() {
        return (<h1 onClick={this.onChange}>{this.state.title}</h1>);
    }
}

看起來好像沒什么區(qū)別孟辑,不使用mobx代碼量還少一點(diǎn)哎甲。所以當(dāng)只維護(hù)一個(gè)有狀態(tài)組件時(shí),無需使用mobx饲嗽。
但是當(dāng)多個(gè)子父組件聯(lián)動(dòng)時(shí)炭玫,使用了mobx,只需在store中維護(hù)一份數(shù)據(jù)貌虾,即可控制多個(gè)組件的狀態(tài)吞加,大大簡(jiǎn)化組件間交互的邏輯,這也是mobx的價(jià)值所在尽狠。

runInAction

@action 只能影響正在運(yùn)行的函數(shù)衔憨,而無法影響當(dāng)前函數(shù)調(diào)用的異步操作。
所以當(dāng)@action中有異步請(qǐng)求時(shí)袄膏,需要用runInAction()包裹践图。調(diào)用后,這個(gè)action方法會(huì)立刻執(zhí)行沉馆。不用runInAction()码党,異步方法運(yùn)行時(shí)會(huì)報(bào)錯(cuò)。
還是第一個(gè)demo斥黑,當(dāng)要改變的數(shù)據(jù)是從后臺(tái)請(qǐng)求到時(shí):

    @action changeTitle() {
        post('post/getTitle', res => {
            runInAction(() => {
                //res.title='已經(jīng)點(diǎn)擊了揖盘!'
                this.title = res.title;
            });
        });
    }

computed——計(jì)算屬性

直接上demo:

useStrict(true);
class Store {
    @observable goods: any = { price: 20, number: 100 };
    @computed get total() {
        return this.goods.price * this.goods.number;
    }
    @action changePrice() {
        this.goods.price = Math.floor(Math.random() * 100);
    }
}

const store = new Store();

@observer
class TitlePanel extends React.Component<{}, {}> {
    render() {
        return (<div>
            <h1>{`單價(jià):${store.goods.price},數(shù)量:${store.goods.number},總價(jià)${store.total}`}</h1>
            <button onClick={() => { store.changePrice() }}>{'點(diǎn)擊改變單價(jià)'}</button>
        </div>);
    }
}
ReactDom.render(<TitlePanel />, document.body);

@computed 修飾的方法一般用來做計(jì)算/單位轉(zhuǎn)換/格式轉(zhuǎn)換等工作。我們當(dāng)然可以用@aciton或者直接在render()中計(jì)算锌奴。

@computed的優(yōu)點(diǎn)是可以緩存計(jì)算后的值扣讼,提升效率。像demo里這種每次都是不同值缨叫,用@computed沒有優(yōu)勢(shì)。

@observable修飾數(shù)組

@observable可以修飾任何js類型荔燎,包括string耻姥、number、object有咨、array琐簇。
修飾array時(shí)會(huì)有一些需要注意的地方,請(qǐng)看demo座享。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末婉商,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子渣叛,更是在濱河造成了極大的恐慌丈秩,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淳衙,死亡現(xiàn)場(chǎng)離奇詭異蘑秽,居然都是意外死亡饺著,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門肠牲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幼衰,“玉大人,你說我怎么就攤上這事缀雳《上” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵肥印,是天一觀的道長(zhǎng)识椰。 經(jīng)常有香客問我,道長(zhǎng)竖独,這世上最難降的妖魔是什么裤唠? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮莹痢,結(jié)果婚禮上种蘸,老公的妹妹穿的比我還像新娘。我一直安慰自己竞膳,他們只是感情好航瞭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著坦辟,像睡著了一般刊侯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锉走,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天滨彻,我揣著相機(jī)與錄音,去河邊找鬼挪蹭。 笑死亭饵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梁厉。 我是一名探鬼主播辜羊,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼词顾!你這毒婦竟也來了八秃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤肉盹,失蹤者是張志新(化名)和其女友劉穎昔驱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體垮媒,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舍悯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年航棱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萌衬。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饮醇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出秕豫,到底是詐尸還是另有隱情朴艰,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布混移,位于F島的核電站祠墅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏歌径。R本人自食惡果不足惜毁嗦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望回铛。 院中可真熱鬧狗准,春花似錦、人聲如沸茵肃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽验残。三九已至捞附,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間您没,已是汗流浹背鸟召。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留氨鹏,地道東北人药版。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像喻犁,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子何缓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容