這篇文章主要講解了“什么是MobX”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“什么是MobX”吧!
成都創(chuàng)新互聯(lián)公司主要從事成都做網(wǎng)站、成都網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)鐵西,10年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18980820575
題外話
在介紹 MobX 的用法之前,先說點(diǎn)題外話,我們可以看一下 MobX 的中文簡(jiǎn)介。在 MobX 的中文網(wǎng)站上寫著:
“MobX 是一個(gè)經(jīng)過戰(zhàn)火洗禮的庫(kù),它通過透明的函數(shù)響應(yīng)式編程使得狀態(tài)管理變得簡(jiǎn)單和可擴(kuò)展。
數(shù)據(jù)流
“戰(zhàn)火洗禮的庫(kù)” 怎么看都感覺很奇怪,讀起來很拗口??,而且網(wǎng)上很多介紹 MobX 的文章都是這么寫的,在 github 翻閱其 README 發(fā)現(xiàn)寫的是:
“MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP).
可以看到作者原本要表達(dá)的意思是 MobX 是經(jīng)過了許多的測(cè)試,擁有比較強(qiáng)的健壯性。下面是通過谷歌翻譯的結(jié)果,看起來也比中文網(wǎng)的表達(dá)要準(zhǔn)確一些。
谷歌翻譯
雖然,我的英文水平也很菜,還是會(huì)盡量看官方的文檔,這樣可以避免一些不必要的誤解。
如何使用?
言歸正傳,MobX 現(xiàn)在的最新版是 6.0,這個(gè)版本的 API 相比于之前有了極大的簡(jiǎn)化,可以說更加好用了。之前的版本是裝飾器風(fēng)格的語法糖,但是裝飾器在現(xiàn)在的 ES 規(guī)范中并不成熟,而且引入裝飾器語法也在增加打包后的代碼體積。綜合考慮后,MobX 6.0 取消了裝飾器語法的 API。
響應(yīng)式對(duì)象
MobX 通過 makeObservable 方法來構(gòu)造響應(yīng)式對(duì)象,傳入的對(duì)象屬性會(huì)通過 Proxy 代理,與 Vue 類似,在 6.0 版本之前使用的是 Object.defineProperty API,當(dāng)然 6.0 也提供了降級(jí)方案。
import { configure, makeObservable, observable, action, computed } from 'mobx' // 使用該配置,可以將 Proxy 降級(jí)為 Object.defineProperty configure({ useProxies: "never" }); // 構(gòu)造響應(yīng)對(duì)象 const store = makeObservable( // 需要代理的響應(yīng)對(duì)象 { count: 0, get double() { return this.count * 2 }, increment() { this.count += 1 }, decrement() { this.count -= 1 } }, // 對(duì)各個(gè)屬性進(jìn)行包裝,用于標(biāo)記該屬性的作用 { count: observable, // 需要跟蹤的響應(yīng)屬性 double: computed, // 計(jì)算屬性 increment: action, // action 調(diào)用后,會(huì)修改響應(yīng)對(duì)象 decrement: action, // action 調(diào)用后,會(huì)修改響應(yīng)對(duì)象 } )
我們?cè)诳纯粗鞍姹镜?MobX,使用裝飾器的寫法:
class Store { @observable count = 0 constructor() { makeObservable(this) } @action increment() { this.count++; } @action decrement() { this.count--; } @computed get double() { return this.count * 2 } } const store = new Store()
這么看起來,好像寫法并沒有得到什么簡(jiǎn)化,好像比寫裝飾器還要復(fù)雜點(diǎn)。下面我們看看 6.0 版本一個(gè)更強(qiáng)大的 API:makeAutoObservable。
makeAutoObservable 是一個(gè)更強(qiáng)大的 makeObservable,可以自動(dòng)為屬性加上對(duì)象的包裝函數(shù),上手成本直線下降。
import { makeAutoObservable } from 'mobx' const store = makeAutoObservable({ count: 0, get double() { return this.count * 2 }, increment() { this.count += 1 }, decrement() { this.count -= 1 } })
計(jì)算屬性
MobX 的屬性與 Vue 的 computed 一樣,在 makeAutoObservable 中就是一個(gè) getter,getter 依賴的值一旦發(fā)生變化,getter 本身的返回值也會(huì)跟隨變化。
import { makeAutoObservable } from 'mobx' const store = makeAutoObservable({ count: 0, get double() { return this.count * 2 } })
當(dāng) store.count 為 1 時(shí),調(diào)用 store.double 會(huì)返回 2。
修改行為
當(dāng)我們需要修改 store 上的響應(yīng)屬性時(shí),我們可以通過直接重新賦值的方式修改,但是這樣會(huì)得到 MobX 的警告??。
const store = makeAutoObservable({ count: 0 }); document.getElementById("increment").onclick = function () { store.count += 1 }
warn
MobX 會(huì)提示,在修改響應(yīng)式對(duì)象的屬性時(shí),需要通過 action 的方式修改。雖然直接修改也能生效,但是這樣會(huì)讓 MobX 狀態(tài)的管理比較混亂,而且將狀態(tài)修改放到 action 中,能夠讓 MobX 在內(nèi)部的事務(wù)流程中進(jìn)行修改,以免拿到的某個(gè)屬性還處于中間態(tài),最后計(jì)算的結(jié)果不夠準(zhǔn)確。
makeAutoObservable 中的所有方法都會(huì)被處理成 action。
import { makeAutoObservable } from 'mobx' const store = makeAutoObservable({ count: 0, get double() { return this.count * 2 }, increment() { // action this.count += 1 }, decrement() { // action this.count -= 1 } })
不同于 Vuex,將狀態(tài)的修改劃分為 mutation 和 action,同步修改放到 mutation 中,異步的操作放到 action 中。在 MobX 中,不管是同步還是異步操作,都可以放到 action 中,只是異步操作在修改屬性時(shí),需要將賦值操作放到 runInAction 中。
import { runInAction, makeAutoObservable } from 'mobx' const store = makeAutoObservable({ count: 0, async initCount() { // 模擬獲取遠(yuǎn)程的數(shù)據(jù) const count = await new Promise((resolve) => { setTimeout(() => { resolve(10) }, 500) }) // 獲取數(shù)據(jù)后,將賦值操作放到 runInAction 中 runInAction(() => { this.count = count }) } }) store.initCount()
如果不調(diào)用 runInAction ,則可以直接調(diào)用本身已經(jīng)存在的 action。
import { runInAction, makeAutoObservable } from 'mobx' const store = makeAutoObservable({ count: 0, setCount(count) { this.count = count }, async initCount() { // 模擬獲取遠(yuǎn)程的數(shù)據(jù) const count = await new Promise((resolve) => { setTimeout(() => { resolve(10) }, 500) }) // 獲取數(shù)據(jù)后,調(diào)用已有的 action this.setCount(count) } }) store.initCount()
監(jiān)聽對(duì)象變更
無論是在 React 還是在小程序中想要引入 MobX,都需要在對(duì)象變更的時(shí)候,通知調(diào)用原生的 setState/setData 方法,將狀態(tài)同步到視圖上。
通過 autorun 方法可以實(shí)現(xiàn)這個(gè)能力,我們可以把 autorun 理解為 React Hooks 中的 useEffect。每當(dāng) store 的響應(yīng)屬性發(fā)生修改時(shí),傳入 autorun 的方法(effect)就會(huì)被調(diào)用一次。
import { autorun, makeAutoObservable } from 'mobx' const store = makeAutoObservable({ count: 0, setCount(count) { this.count = count }, increment() { this.count++ }, decrement() { this.count-- } }) document.getElementById("increment").onclick = function () { store.count++ } const $count = document.getElementById("count") $count.innerText = `${store.count}` autorun(() => { $count.innerText = `${store.count}` })
每當(dāng) button#increment 按鈕被點(diǎn)擊的時(shí)候,span#count 內(nèi)的值就會(huì)自動(dòng)進(jìn)行同步。??查看完整代碼。
效果演示
除了 autorun ,MobX 還提供了更精細(xì)化的監(jiān)聽方法:reaction、 when。
const store = makeAutoObservable({ count: 0, setCount(count) { this.count = count }, increment() { this.count++ }, decrement() { this.count-- } }) // store 發(fā)生修改立即調(diào)用 effect autorun(() => { $count.innerText = `${store.count}` }); // 第一個(gè)方法的返回值修改后才會(huì)調(diào)用后面的 effect reaction( // 表示 store.count 修改后才會(huì)調(diào)用 () => store.count, // 第一個(gè)參數(shù)為當(dāng)前值,第二個(gè)參數(shù)為修改前的值 // 有點(diǎn)類似與 Vue 中的 watch (value, prevValue) => { console.log('diff', value - prevValue) } ); // 第一個(gè)方法的返回值為真,立即調(diào)用后面的 effect when(() => store.count > 10, () => { console.log(store.count) }) // when 方法還能返回一個(gè) promise (async function() { await when(() => store.count > 10) console.log('store.count > 10') })()
感謝各位的閱讀,以上就是“什么是MobX”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)什么是MobX這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!