名字很长很绕靠口,总的来讲,本文是对开发小程序过程当中使用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