名字很長很繞靠口,總的來講,本文是對開發小程序過程當中使用mobx
的一個總結。前端
狀態管理,相比你們也很熟悉,顧名思義,是對前端頁面繁複的狀態進行管理,在此,我也不過多贅述。vue
因此雖然是是用在小程序上,不過我想對於WebApp
的狀態管理,也有這麼一丟丟啓發。react
爲何要進行狀態管理?
如今的小程序儼然是Hybrid App
,又像是PWA
,但固然也是一個WebApp
,更不用說他的語法和vue
略微有這麼一丟丟類似。有react
和vue
的實踐在前,因此對於小程序上那麼多的頁面狀態和數據緩存,勢必也要引入一個狀態管理工具git
爲何是mobx
方便,快捷,學習成本低,固然也是仁者見仁智者見智github
在小程序中引入mobx
在這裏我使用了wechat-weapp-mobx這個庫。在./libs
目錄下放入mobx.js
和observer.js
這兩個庫,同時在./store
目錄下新建store.js
用於存放全局狀態。小程序
創建store
因爲小程序中不支持@decorate
裝飾器,因此採用了extendObservable
的寫法。另外,小程序支持import
語法和require
語法。我比較喜歡import
語法,大家呢?我認爲在action
中不應寫入複雜邏輯代碼,保持簡潔性和可複用性,大家怎麼看緩存
// store.js // 引入必須的庫 const mobx = require('../libs/mobx'); const extendObservable = require('../libs/mobx').extendObservable; const computed = require('../libs/mobx').computed; const toJS = require('../libs/mobx').toJS; let store = function () { extendObservable(this, { // observable data players: [], // computed data get count() { return this.players.length; } }); // action this.addPlayer = name => { let len = this.count; //此處調用computed data let id = len === 0 ? 1 : this.players[len - 1].id + 1; this.players.push(new player(name, id)); } } export default store;
全局引入store
衆所周知,使用mobx
的store
要使用new store()
,若是咱們想全局調用,勢必不可能在每一個頁面都new
一個sotre
,由於這樣的話每一個頁面的store
都是一個全新的store
。在這裏,我在app.js
裏引入store
,並掛載在全局變量globalData
下。另外,小程序中不支持路徑的省略。網絡
//app.js const observer = require('./libs/observer').observer; import store from './stores/index'; // 小程序中不支持省略調用 App(observer({ onLaunch: function () { }, globalData: { store: new store() } }))
在pages裏調用全局的store
能夠同時使用內置的data
進行雙向綁定哦app
// index.js const observer = require('../../libs/observer').observer; let app = getApp(); Page(observer({ data: { mes: 'hello jim green' }, props: { store: app.globalData.store }, }))
在頁面中調用storeide
<view class="players-list"> <view class="players-item" wx:for="{{props.store.players}}" wx:key="{{item.id}}"> // 調用observable data <text class="players">{{item.id}}:{{item.name}}</text> </view> <view>{{props.sotre.count}}</view> // 調用computed data </view>
更新多個頁面的store
問題來了,這個時候,多個頁面的store
仍是獨立的,如何所有更新呢?答案就是在onShow
和onHide
或者onUnload
這三個生命週期函數中跟新全局的store
onShow: function() { // 顯示時更新本頁面store this.props.store = app.globalData.store }, onHide: function() { // 隱藏時更新全局store app.globalData.store = this.props.store; }, onUnload: function() { // 頁面跳轉返回時更新全局store app.globalData.store = this.props.store; },
store和localStorage的長效存儲
考慮到網絡還有程序崩潰的問題,我將store
存儲在localStorage
中以便恢復,我在index.js
的onLoad
中調用get storage
,在onHide
中set storage
。因爲toJS
方法返回了一個不支持[Symbol.iterator]()
的對象,因此在store裏進行了以下設置
// index.js onLoad: function () { let store = wx.getStorageSync('store'); if(store) { this.props.store.formStorageToStore(store); } }, onHide: function () { let store =this.props.store.currentStore; wx.setStorageSync('store', store) }, // store.js get currentStore() { let {players,games,currentGame,hidden,filter} = toJS(this); return {players,games,currentGame,hidden,filter}; } this.formStorageToStore = ({players,games,currentGame,hidden,filter}) => { this.players = players; this.games = games; this.currentGame = currentGame; this.hidden = hidden; this.filter = filter; }
講點其餘
本項目的示例小程序地址weapp-bmscore,歡迎各位老鐵點個關注666