在小程序中,常常有些数据需要在几个页面或组件中共享。对于这样的数据,在 web 开发中,有些朋友使用过 redux 、 vuex 之类的 状态管理 框架。在小程序开发中,也有不少朋友喜欢用 MobX ,说明这类框架在实际开发中非常实用。
小程序团队近期也开源了 MobX 的辅助模块,使用 MobX 也更加方便。那么,在这篇文章中就来介绍一下 MobX 在小程序中的一个简单用例!
在小程序中引入 MobX
在小程序项目中,可以通过 npm 的方式引入 MobX 。如果你还没有在小程序中使用过 npm ,那先在小程序目录中执行命令:
npm init -y
引入 MobX :
npm install --save mobx-miniprogram mobx-miniprogram-bindings
(这里用到了 mobx-miniprogram-bindings 模块,模块说明在这里: https://developers.weixin.qq.com/miniprogram/dev/extended/functional/mobx.html 。)
npm 命令执行完后,记得在开发者工具的项目中点一下菜单栏中的 工具
- 构建 npm
。
MobX 有什么用呢?
试想这样一个场景:制作一个天气预报资讯小程序,首页是列表,点击列表中的项目可以进入到详情页。
首页如下:
详情页如下:
每次进入首页时,需要使用 wx.request
获取天气列表数据,之后将数据使用 setData 应用到界面上。进入详情页之后,再次获取指定日期的天气详情数据,展示在详情页中。
这样做的坏处是,进入了详情页之后需要再次通过网络获取一次数据,等待网络返回后才能将数据展示出来。
事实上,可以在首页获取天气列表数据时,就一并将所有的天气详情数据一同获取回来,存放在一个 数据仓库 中,需要的时候从仓库中取出来就可以了。这样,只需要进入首页时获取一次网络数据就可以了。
MobX 可以帮助我们很方便地建立数据仓库。接下来就讲解一下具体怎么建立和使用 MobX 数据仓库。
建立数据仓库
数据仓库通常专门写在一个独立的 js 文件中。
import { observable, action } from 'mobx-miniprogram'
// 数据仓库
export const store = observable({
list: [], // 天气数据(包含列表和详情)
// 设置天气列表,从网络上获取到数据之后调用
setList: action(function (list) {
this.list = list
}),
})
在上面数据仓库中,包含有数据 list
(即天气数据),还包括了一个名为 setList
的 action ,用于更改数据仓库中的数据。
在首页中使用数据仓库
如果需要在页面中使用数据仓库里的数据,需要调用 createStoreBindings
来将仓库中的数据绑定到页面数据中,然后就可以在页面中直接使用仓库数据了。
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from './store'
Page({
onLoad() {
// 绑定 MobX store
this.storeBindings = createStoreBindings(this, {
store, // 需要绑定的数据仓库
fields: ['list'], // 将 this.data.list 绑定为仓库中的 list ,即天气数据
actions: ['setList'], // 将 this.setList 绑定为仓库中的 setList action
})
// 从服务器端读取数据
wx.showLoading()
wx.request({ // 请求网络数据
// ...
success: (data) => {
wx.hideLoading()
// 调用 setList action ,将数据写入 store
this.setList(data)
}
})
},
onUnload() {
// 解绑
this.storeBindings.destroyStoreBindings()
},
})
这样,可以在 wxml 中直接使用 list :
<view class="item" wx:for="{{list}}" wx:key="date" data-index="{{index}}">
<!-- 这里可以使用 list 中的数据了! -->
<view class="title">{{item.date}} {{item.summary}}</view>
<view class="abstract">{{item.temperature}}</view>
</view>
在详情页中使用数据仓库
在详情页中,同样可以使用 createStoreBindings
来将仓库中的数据绑定到页面数据中:
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from './store'
Page({
onLoad(args) {
// 绑定 MobX store
this.storeBindings = createStoreBindings(this, {
store, // 需要绑定的数据仓库
fields: ['list'], // 将 this.data.list 绑定为仓库中的 list ,即天气数据
})
// 页面参数 `index` 表示要展示哪一条天气详情数据,将它用 setData 设置到界面上
this.setData({
index: args.index
})
},
onUnload() {
// 解绑
this.storeBindings.destroyStoreBindings()
},
})
这样,这个页面 wxml 中也可以直接使用 list :
<view class="title">{{list[index].date}}</view>
<view class="content">温度 {{list[index].temperature}}</view>
<view class="content">天气 {{list[index].weather}}</view>
<view class="content">空气质量 {{list[index].airQuality}}</view>
<view class="content">{{list[index].details}}</view>
完整示例
完整例子可以在这个代码片段中体验: https://developers.weixin.qq.com/s/YhfvpxmN7HcV
这个就是 MobX 在小程序中最基础的玩法了。相关的 npm 模块文档可参考 mobx-miniprogram-bindings 和 mobx-miniprogram 。
MobX 在实际使用时还有很多好的实践经验,感兴趣的话,可以阅读一些其他相关的文章。
打包成json 页面传值不是也很香吗?跨的页面比较多使用全局变量应该也可以吧?有没有性能优势对比的文章,好让我们择优使用
为什么在作者的基础上更新store ,没能达到同步更新效果,是bug 还是我书写用法错误,请教
https://developers.weixin.qq.com/s/2mHJdLmz74fX
目前想到的方法是:
1、store/index.js 中的 setQuery 函数 ,外部传参,queryItems为字符串类型,然后再如图代码重新 JSON.parse ,解决wxml 未及时更新的问题。。。
但是楼主DEMO也没有更新数据同步更新视图这一项呀?楼主讲的具体实战中,重新生成一个新对象是怎么操作???
数字是直接行得通的,其他的不知道怎么样?
https://developers.weixin.qq.com/s/IQpuRUm57ufZ
你的list初始值打印出来是什么样的?为什么我的是这样?,一直到999,值都是undefined
如果直接定义这样的action:
testAction: action(async function(){ ... })
在Component中绑定到this.testAsync。
这时候直接调用await this.testAsync则不起作用(),因为绑定到this的过程套了一层同步函数apply调用。。
如果直接调用await store.testAsync()则正常。
想问问是有意这样设计还是有别的原因。如果直接使用await store.xxx()会引发问题吗。
请问可以使用异步action吗?
有个学习成本更低 体积更小的 onfire.js