评论

使用 MobX 来管理小程序的跨页面数据

MobX 可以帮助小程序管理跨页面的数据。小程序团队近期开源了 MobX 的小程序辅助模块,使用 MobX 也更加方便。在这篇文章中就来介绍一下 MobX 在小程序中的一个简单用例。

在小程序中,常常有些数据需要在几个页面或组件中共享。对于这样的数据,在 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-bindingsmobx-miniprogram

MobX 在实际使用时还有很多好的实践经验,感兴趣的话,可以阅读一些其他相关的文章。

最后一次编辑于  2019-11-01  
点赞 17
收藏
评论

16 个评论

  • Schnuffel
    Schnuffel
    2021-06-18

    小程序 mobx-miniprogram 这个库拥有 typescript 支持感觉很好,但是需要配合 mobx-miniprogram-bindings 这个库使用,而这个库没有声明文件,开发起来特别困难

    2021-06-18
    赞同 3
    回复
  • 洁
    2022-03-28

    我在分包页面里用mobx,不支持,总是提示找不到相应文件

    2022-03-28
    赞同 1
    回复 1
    • 哈罗哈皮
      哈罗哈皮
      2022-10-19
      然后你解决了吗
      2022-10-19
      回复
  • 天心
    天心
    2020-04-29

    请问如何在单独的js中更改store中的值(不在Componet或者Page实例中,而是其引用的js中直接更改,因为一些公共的方法中需要更改state)?

    2020-04-29
    赞同 1
    回复 4
    • LastLeaf
      LastLeaf
      2020-04-29
      都行的。就像普通的 mobx 用法一样。
      2020-04-29
      回复
    • 天心
      天心
      2020-04-29回复LastLeaf
      好的,谢谢。刚才是因为action中定义使用了箭头函数,改为普通function就可以了。
      2020-04-29
      1
      回复
    • 草场坡彭于晏😿
      草场坡彭于晏😿
      2022-07-27回复LastLeaf
      具体怎么用呢
      2022-07-27
      1
      回复
    • change
      change
      07-23
      07-23
      回复
  • 尹约
    尹约
    02-04

    在页面中修改store里的变量的值,为什么没有更新?

    02-04
    赞同
    回复
  • 去年夏天
    去年夏天
    2023-12-03

    额,现在是 2023 年底了,这个方案依旧有效么。是否有更优秀的方案出现呢?

    2023-12-03
    赞同
    回复 1
  • Theory
    Theory
    2022-12-23

    https://developers.weixin.qq.com/miniprogram/dev/extended/functional/mobx.html 404了

    2022-12-23
    赞同
    回复
  • 武汉杰跃信息技术有限公司_胡杰
    武汉杰跃信息技术有限公司_胡杰
    2022-11-15

    请问下,mbox有没有成功的回调函数

    2022-11-15
    赞同
    回复 2
    • 怪人
      怪人
      2022-12-04
      我想问有没有页面使用store里的list渲染成功的回调函数。
      2022-12-04
      回复
    • 我叫肥坚
      我叫肥坚
      05-02
      +1 我也在找这个解决方法,我想在小程序一加载时,就从服务器获取所有页面都需要用到的数据。
      05-02
      回复
  • Q1an
    Q1an
    2022-06-21

    请问需要用到store数据的每一个页面都要在onLoad中绑定Mobx store吗?

    2022-06-21
    赞同
    回复
  • 景夏
    景夏
    2022-01-20

    想问下。如果在app.js里面引入的话,如何销毁?

    我看都是在page或者componet里面引入,在onUnload生命周期里面销毁。但是在app.js里面onlanch只引入,不销毁有没有问题?主要是为了解决入口文件的问题。大家都是怎么管理全局数据的,不需要在app.js里面去初始化么?难道是在每个用的地方去判断是否初始化么?

    2022-01-20
    赞同
    回复 3
    • 草场坡彭于晏😿
      草场坡彭于晏😿
      2022-07-27
      在app.js里引入 怎么修改状态,提示setData不存在啊?
      2022-07-27
      回复
    • 冉羽冉羽
      冉羽冉羽
      2023-09-04回复草场坡彭于晏😿
      我提示也和你一样,请问你找到解决方案了吗?
      2023-09-04
      回复
    • 我叫肥坚
      我叫肥坚
      05-02回复草场坡彭于晏😿
      +1 我也在找这个解决方法,我想在小程序一加载时,就从服务器获取所有页面都需要用到的数据。
      05-02
      回复
  • 渔船
    渔船
    2021-04-14

    请问一个page绑定多个store,测试以下写法可以执行,方案是否有什么隐患?

    单个页面绑定多个store有没有推荐的方案?

    2021-04-14
    赞同
    回复 4
    • LastLeaf
      LastLeaf
      2021-04-20
      可以。不过建议参考目前最新版本文档里的写法。
      2021-04-20
      回复
    • 巽
      2021-11-05回复LastLeaf
      具体呢
      2021-11-05
      回复
    • 巽
      2021-11-05
      你怎么处理的
      2021-11-05
      回复
    • l will be there
      l will be there
      2023-09-26回复LastLeaf
      关键是文档在哪呢
      2023-09-26
      回复

正在加载...

登录 后发表内容