初识小程序-全局数据共享(状态管理)

217 阅读2分钟

全局数据共享是为了解决组件之间数据共享的问题。

全局数据共享方案

开发中常用的全局共享方案有:Vuex、Redux、MobX等。在小程序中,可使用mobx-miniprogram配合mobx-miniprogram-bindings实现全局数据共享。其中:

  • mobx-miniprogram用来创建Store实例对象【创建全局数据共享池】
  • mobx-miniprogram-bindings用来把Store中的共享数据或方法,绑定到组件或页面中使用

安装MobX相关包

npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1

构建npm

创建store

新增store目录,在store目录中新怎store.js文件,用来专门创建Store的实例对象

image.png

// store.js
// observable 用来创建检测对象,对象中的属性会被转换成响应式数据
// action 用来显示定义action方法
import {action, observable} from "mobx-miniprogram"
export const store=observable({
  // 数据字段
  numA:1,
  numB:2,
  // 计算属性
  get sum(){
    return this.numA+this.numB
  },
  // actions 方法,用来修改 store 中的数据
  updateNum1:action(function(step){
    this.numA+=step;
  }),
  updateNum2:action(function(step){
    this.numB+=step;
  }),
})

将store中成员绑定到页面中

方式一

// behavior -> userBehaviors.js
import {BehaviorWithStore} from "mobx-miniprogram-bindings"
import {store} from "../store/store"
export const userBehavior = BehaviorWithStore({
  storeBindings:{
    store, 
    fields:['userInfo'],
    actions:["setUserInfo"]
  }
})
import {userBehavior} from "../../behavior/userBehaviors"
// pages/list/list.js
Page({
  behaviors:[userBehavior],

方式二

将store中的数据绑定到页面,在onLoad生命周期中绑定,页面卸载时卸载实例,在onUnload中清理

import {createStoreBindings} from "mobx-miniprogram-bindings"
import {store} from "../../store/store"
Page({
// 监听页面加载
  onLoad(){
    this.storeBindings=createStoreBindings(this,{
      store,
      fields:["numA","numB","sum"],
      actions:['updateNum1'],
    })
  },
  stepHandler(e){
    this.updateNum1(e.target.dataset.step)
  },
  // 监听页面卸载
  onUnload(){
    this.storeBindings.destroyStoreBindings();
  },
<view>numA:{{numA}} numB:{{numB}} sum:{{sum}}</view>
<van-button type="primary" bind:tap="stepHandler" data-step="{{1}}">store</van-button>

将store中成员绑定到组件中

方式一

// 导入ComponentWithStore
import {ComponentWithStore} from "mobx-miniprogram-bindings"
// 导入store对象
import {store} from "../../store/store"

// pages/mobx/mobx.js
// 导入ComponentWithStore 替换 Component方法构造页面
ComponentWithStore({
  // 让页面和store建立关联
  storeBindings:{
   store:store, // 需要绑定的store对象
   fields:['token'], // 需要从store对象中映射哪些数据
   actions:['setToken'], //从store对象中映射actions方法
  },

方式二

import {storeBindingsBehavior} from "mobx-miniprogram-bindings"
import {store} from "../../store/store"
Component({
  // 通过storeBindingsBehavior实现自动绑定
  behaviors:[storeBindingsBehavior],
  storeBindings:{
    store,
    fields:{
      numA:()=>store.numA,     // 绑定字段的第1种方式
      numB:(store)=>store.numB,// 绑定字段的第2种方式
      sum:"sum"                // 绑定字段的第3种方式
    },
    actions:{
      updateNum2:"updateNum2"
    }
  },
  methods: {
    stepHandler(e){
      this.updateNum2(e.target.dataset.step)
    }, 
    ...
  }
  ...
<view>numA:{{numA}} numB:{{numB}} sum:{{sum}}</view>
<van-button type="primary" bind:tap="stepHandler" data-step="{{1}}">store</van-button>

绑定多个store以及命名空间

需要将storeBindings改为数组的形式

import {BehaviorWithStore} from "mobx-miniprogram-bindings"
import {storeA} from "../store/storeA"
import {storeB} from "../store/storeB"
export const userBehavior = BehaviorWithStore({
  storeBindings:[
      {
        storeA, 
        fields:['userInfo'],
        actions:["setUserInfo"]
      },
      {
        storeB, 
        fields:['userInfo'],
        actions:["setUserInfo"]
      }
  ]
})

两个store都有setUserInfo方法,有两种方式:

  1. 可使用对象的方式,修改别名
  2. 添加命名空间
// 修改别名
storeBindings:[
  {
    storeA, 
    fields:['userInfo'],
    actions:["setUserInfo"]
  },
  {
    storeB, 
    fields:{
     userInfoA:"userInfo",
    },
    actions:{
     setUserInfoB:"setUserInfo",
    }
  }
]
// 添加命名空间
storeBindings:[
  {
    storeA, 
    fields:['userInfo'],
    actions:["setUserInfo"]
  },
  {
    storeB, 
    namespace:"cloneStore",
    // 数据冲突,添加命名空间可以解决
    // 添加命名空间后想访问数据,需要加上命名空间名字才可以 
    // 如:cloneStore.userInfo
    fields:['userInfo'],
    // 方法冲突,依然需要使用对象方式
    // actions:["setUserInfo"],
    actions:{
     setUserInfoB:"setUserInfo",
    }
  }
]