您好,登錄后才能下訂單哦!
這篇文章主要講解了“什么是MobX”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“什么是MobX”吧!
題外話
在介紹 MobX 的用法之前,先說點題外話,我們可以看一下 MobX 的中文簡介。在 MobX 的中文網站上寫著:
“MobX 是一個經過戰火洗禮的庫,它通過透明的函數響應式編程使得狀態管理變得簡單和可擴展。
數據流
“戰火洗禮的庫” 怎么看都感覺很奇怪,讀起來很拗口??,而且網上很多介紹 MobX 的文章都是這么寫的,在 github 翻閱其 README 發現寫的是:
“MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP).
可以看到作者原本要表達的意思是 MobX 是經過了許多的測試,擁有比較強的健壯性。下面是通過谷歌翻譯的結果,看起來也比中文網的表達要準確一些。
谷歌翻譯
雖然,我的英文水平也很菜,還是會盡量看官方的文檔,這樣可以避免一些不必要的誤解。
如何使用?
言歸正傳,MobX 現在的最新版是 6.0,這個版本的 API 相比于之前有了極大的簡化,可以說更加好用了。之前的版本是裝飾器風格的語法糖,但是裝飾器在現在的 ES 規范中并不成熟,而且引入裝飾器語法也在增加打包后的代碼體積。綜合考慮后,MobX 6.0 取消了裝飾器語法的 API。
響應式對象
MobX 通過 makeObservable 方法來構造響應式對象,傳入的對象屬性會通過 Proxy 代理,與 Vue 類似,在 6.0 版本之前使用的是 Object.defineProperty API,當然 6.0 也提供了降級方案。
import { configure, makeObservable, observable, action, computed } from 'mobx' // 使用該配置,可以將 Proxy 降級為 Object.defineProperty configure({ useProxies: "never" }); // 構造響應對象 const store = makeObservable( // 需要代理的響應對象 { count: 0, get double() { return this.count * 2 }, increment() { this.count += 1 }, decrement() { this.count -= 1 } }, // 對各個屬性進行包裝,用于標記該屬性的作用 { count: observable, // 需要跟蹤的響應屬性 double: computed, // 計算屬性 increment: action, // action 調用后,會修改響應對象 decrement: action, // action 調用后,會修改響應對象 } )
我們在看看之前版本的 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()
這么看起來,好像寫法并沒有得到什么簡化,好像比寫裝飾器還要復雜點。下面我們看看 6.0 版本一個更強大的 API:makeAutoObservable。
makeAutoObservable 是一個更強大的 makeObservable,可以自動為屬性加上對象的包裝函數,上手成本直線下降。
import { makeAutoObservable } from 'mobx' const store = makeAutoObservable({ count: 0, get double() { return this.count * 2 }, increment() { this.count += 1 }, decrement() { this.count -= 1 } })
計算屬性
MobX 的屬性與 Vue 的 computed 一樣,在 makeAutoObservable 中就是一個 getter,getter 依賴的值一旦發生變化,getter 本身的返回值也會跟隨變化。
import { makeAutoObservable } from 'mobx' const store = makeAutoObservable({ count: 0, get double() { return this.count * 2 } })
當 store.count 為 1 時,調用 store.double 會返回 2。
修改行為
當我們需要修改 store 上的響應屬性時,我們可以通過直接重新賦值的方式修改,但是這樣會得到 MobX 的警告??。
const store = makeAutoObservable({ count: 0 }); document.getElementById("increment").onclick = function () { store.count += 1 }
warn
MobX 會提示,在修改響應式對象的屬性時,需要通過 action 的方式修改。雖然直接修改也能生效,但是這樣會讓 MobX 狀態的管理比較混亂,而且將狀態修改放到 action 中,能夠讓 MobX 在內部的事務流程中進行修改,以免拿到的某個屬性還處于中間態,最后計算的結果不夠準確。
makeAutoObservable 中的所有方法都會被處理成 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,將狀態的修改劃分為 mutation 和 action,同步修改放到 mutation 中,異步的操作放到 action 中。在 MobX 中,不管是同步還是異步操作,都可以放到 action 中,只是異步操作在修改屬性時,需要將賦值操作放到 runInAction 中。
import { runInAction, makeAutoObservable } from 'mobx' const store = makeAutoObservable({ count: 0, async initCount() { // 模擬獲取遠程的數據 const count = await new Promise((resolve) => { setTimeout(() => { resolve(10) }, 500) }) // 獲取數據后,將賦值操作放到 runInAction 中 runInAction(() => { this.count = count }) } }) store.initCount()
如果不調用 runInAction ,則可以直接調用本身已經存在的 action。
import { runInAction, makeAutoObservable } from 'mobx' const store = makeAutoObservable({ count: 0, setCount(count) { this.count = count }, async initCount() { // 模擬獲取遠程的數據 const count = await new Promise((resolve) => { setTimeout(() => { resolve(10) }, 500) }) // 獲取數據后,調用已有的 action this.setCount(count) } }) store.initCount()
監聽對象變更
無論是在 React 還是在小程序中想要引入 MobX,都需要在對象變更的時候,通知調用原生的 setState/setData 方法,將狀態同步到視圖上。
通過 autorun 方法可以實現這個能力,我們可以把 autorun 理解為 React Hooks 中的 useEffect。每當 store 的響應屬性發生修改時,傳入 autorun 的方法(effect)就會被調用一次。
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}` })
每當 button#increment 按鈕被點擊的時候,span#count 內的值就會自動進行同步。??查看完整代碼。
效果演示
除了 autorun ,MobX 還提供了更精細化的監聽方法:reaction、 when。
const store = makeAutoObservable({ count: 0, setCount(count) { this.count = count }, increment() { this.count++ }, decrement() { this.count-- } }) // store 發生修改立即調用 effect autorun(() => { $count.innerText = `${store.count}` }); // 第一個方法的返回值修改后才會調用后面的 effect reaction( // 表示 store.count 修改后才會調用 () => store.count, // 第一個參數為當前值,第二個參數為修改前的值 // 有點類似與 Vue 中的 watch (value, prevValue) => { console.log('diff', value - prevValue) } ); // 第一個方法的返回值為真,立即調用后面的 effect when(() => store.count > 10, () => { console.log(store.count) }) // when 方法還能返回一個 promise (async function() { await when(() => store.count > 10) console.log('store.count > 10') })()
感謝各位的閱讀,以上就是“什么是MobX”的內容了,經過本文的學習后,相信大家對什么是MobX這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。