likes
comments
collection
share

微信小程序之状态管理 - Mobx

作者站长头像
站长
· 阅读数 4

微信小程序之状态管理

技术栈:mobx-miniprogram-bindings

使用Mobx绑定辅助库

使用方法

  1. 安装 mobx-miniprogrammobx-miniprogram-bindings

    npm install --save mobx-miniprogram mobx-miniprogram-bindings
    
  2. 构建npm

  3. 创建Mobx Store

    store.js

    //根目录下创建路径 - 路径仅供参考
    // models(store)/index.js - 名字随意,官方给的是models,二级目录名字看使用场景,如果是用户可以是user.js,如果是购物车可以是cars.js
    // 代码块
    import { observable,action } from 'mobx-miniprogram'
    export const store = observable({
    //数据字段 - 类似于vuex中的state
    numA:1,
    numB:2,
     //计算属性
     get sum() {
       return this.numA + this.numB 
     },
        //actions
     update:action(function(){
         const sum = this.sum;
         this.numA = this.numB;
         this.numB = sum
     })
    })
    

    observable方法:将普通的js对象转换为可观察对象

    在这个状态管理仓库中利用observable函数定义了几个属性和方法:

    其中numA,numB是状态数据

    get关键字定义计算属性,sum是计算属性用于计算numA,numB和

    update(动作),action装饰器定义的动作 - 用于修改可观察对象的属性。档update触发时,确保数据的更新。

    一句话:直接定义状态数据,get做逻辑运算,actions修改数据

  4. 使用(2种方式 - component/page)

    component中使用 - 使用behavior绑定

    做法: 使用storeBindingsBehavior

    import { storeBindingsBehavior } from "mobx-moniprogram-bindings"
    import { store } from "../../store/store"
    Component({
     behaviors:[storeBindingsBehavior],
     data:{
         someData:"...",
     },
     storeBindings:{
         store,
         fields:{
             numA:() => store.numA,
             numB:(store) => store.NumB
             sum:"sum"
         },
         actions:{
             // buttonTap - 绑定按钮点击动作
             buttonTap:'update'
         }
     }
     methods:{
        myMethod() {
        this.data.sum; // 来自于 MobX store 的字段
        },
    }
    })
    

    behaviors:小程序内置属性 - 用于指定要应用的行为

    someData:"...":定义一个初始值是“...”的变量

    storeBindings:指定要绑定的属性和动作 - 来自mobx-miniprogram-bindings库 - 用于在小程序中实现可观察对象和组件之间的绑定。其中的键表示要绑定的属性或动作,值是一个函数或一个字符串。

    store:指定要绑定的可观察对象

    fields:指定要绑定的属性

    actions:指定要绑定的动作

    常见的绑定动作:

    1. click - buttonClick
    2. change - inputChange
    3. submit - formSubmit
    4. keydown - keyPressed
    5. swiperChange - swiperSlideChange
    6. scrollToLower - loadMoreData

    this.data.sum:调用store里面的sum方法,值就是sum的返回值


    在page构造器中使用 - 手工绑定

    做法:createStoreBindings

    import { createStoreBindings } from 'mobx-miniprogram-bindings'
    import { store } from '../../store/store'
    Page({
        //页面初始数据
        data:{
            someData:'...'
        },
        onLoad(option){
            //在onload中创建
            this.storeBindings = createStoreBindings(this,{
                store,
                fields:['numA','numB','sum'],
                actions:['update']
            })
        },
        onUnload(){
            //在页面卸载的时候清理
            this.storeBindings.destroyStoreBindings()
        },
        myMethod(){
            this.data.sum
        }
    })
    

    无论是哪种绑定方式,都必须提供一个绑定配置对象

    字段名类型含义
    storeobservable默认的store
    fields数组或对象用于指定需要绑定的data字段
    actions数组或者对象用于指定需要映射的actions

    fields有三种形式

    • 数组形式:指定data中哪些字段来源于store。例如['numA','numB','sum']
    • 映射形式:指定data中哪些字段来源于store以及它们在store中对应的名字。例如{a:'numA',b:'numB'},此时this.data.a === store.numA,this.data.b === store.numB
    • 函数形式:指定data中每个字段的计算方法。例如{a:()=> store.numA,b:()=>anotherStore.numB},此时this.data.a === store.numA,this.data.b === anotherStore.numB

    以上三种形式中,映射形式和函数形式可以在一个配置中同时使用,如果仅使用了函数形式,那么store字段可以为空,否则store字段必填

    actions

    用于将store中的一些actions放入到页面或者自定义组件的this下,来方便触发一些actions。有两种形式

    • 数组形式:例如['update'],此时this.update === store.update
    • 映射形式:例如{buttonTap:'update'},此时this.buttonTap === store.update

    只要actions不为空,则store字段必填

注意事项

延迟更新与立刻更新

为了提升性能,在 store 中的字段被更新后,并不会立刻同步更新到 this.data 上,而是等到下个 wx.nextTick 调用时才更新。(这样可以显著减少 setData 的调用次数。)

如果需要立刻更新,可以调用:

  • this.updateStoreBindings() (在 behavior 绑定 中)
  • this.storeBindings.updateStoreBindings() (在 手工绑定 中)

与 miniprogram-computed 一起使用

miniprogram-computed 时,在 behaviors 列表中 computedBehavior 必须在后面:

   Component({
     behaviors: [storeBindingsBehavior, computedBehavior],
     /* ... */
   });

关于部分更新

如果只是更新对象中的一部分(子字段),是不会引发界面变化的!例如:

   Component({
     behaviors: [storeBindingsBehavior],
     storeBindings: {
       store,
       fields: ["someObject"],
     },
   });

如果尝试在 store 中:

   this.someObject.someField = "xxx";

这样是不会触发界面更新的。请考虑改成:

   this.someObject = Object.assign({}, this.someObject, { someField: "xxx" });

官方参考文档:mobx-miniprogram-bindings - npm (npmjs.com)

补充 - 关于监听状态仓库数据变化问题

reaction

通过在store里面添加观察者来监听数据的变化

// store.js
import { observable,action,reaction} from 'mobx-miniprogram'
export const store = observable({
  // 数据字段
  numA: 1,
  numB: 5,
  // 计算属性
  get sum() {
    return this.numA + this.numB
  },
  // actions
  update: action(function () {
    const sum = this.sum
    this.numA = this.numB
    this.numB = sum
  })
})
// 添加观察者来监听数据变化
reaction(
  () => store.sum, // 监听的数据
  (sum, reaction) => {
    console.log(`sum 发生变化,新值为: ${sum}`)
    // 在这里可以执行相应的操作
  }
)

在需要的页面调用

// pages/home/home.js
import {
  createStoreBindings
} from 'mobx-miniprogram-bindings'
import {
  store
} from '../../store/store'
import { reaction } from 'mobx-miniprogram'
Page({
  /**
   * 页面的初始数据
   */
  data: {
    someData: '...',
  },
  back() {
    wx.navigateBack({
      url: '/pages/index/index',
    })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    // 自动更新数据
    this.storeBindings = createStoreBindings(this, {
      store,
      fields: ['numA', 'numB', 'sum'],
      actions: ['update'],
    })
    // 手动调用 reaction 来监听状态数据变化
    reaction(
      () => ({
        numA: store.numA,
        numB: store.numB,
        sum: store.sum
      }),
      (data) => {
        console.log('状态数据发生变化:', data)
        // 在这里可以执行相应的操作
      }
    )
  },
  onUnload() {
    this.storeBindings.destroyStoreBindings()
    // 在页面卸载时取消 reaction 监听
    reaction()
  },
  myMethod() {
    this.data.sum // 来自于 MobX store 的字段
  },
})

微信小程序之状态管理 - Mobx