【微信小程序】微信小程序如何使用 MobX 进行状态管理?

news2024/9/20 8:52:11

微信小程序官方在 2019 年针对小程序发布了 MobX 辅助绑定库,可以让我们在微信小程序中使用 Mobx 进行状态管理:

  • mobx-miniprogram:相当于 MobX;
  • mobx-miniprogram-bindings:针对小程序的 MobX 辅助绑定库,类似 mobx-react;
    这篇文章和大家分享为什么要使用 MobX,我对 Mobx 核心概念的理解,以及如何在微信小程序中使用 Mobx。

为什么要用 Mobx

关于为什么要在小程序使用 MobX,可以看小程序 MobX 绑定库官方开发者的一个回复:

问:打包成 json 页面传值不是也很香吗?跨的页面比较多使用全局变量应该也可以吧?

答:那样的话每次数据变动都得传,是“过程式”的方法。状态管理框架在处理数据项需要在多个页面间同步的情况中会更加方便。

再看另一个问答:

问:在小程序中,可使用 mobx-miniprogram 配合 mobx-miniprogram-bindings 实现全局数据共享,也可以用 globalData 是实现数据共享。请问登录之后的用户信息应该放在哪里?

答:globalData 一般适用于放置一些极少改变的全局状态。事实上,也可以通过 require 一个独立的 js 文件来代替 globalData 。MobX (和类似的状态管理库)适用于维护需要跟踪更新的界面状态数据。所以用户信息还是建议放在 globalData 里管理。

Mobx 的核心概念

要在微信小程序中使用 MobX,首先要了解 MobX,要了解 MobX,首先要知道 MobX 的三个核心概念:

  • observable:顾名思义,这是一个可以被监测的对象,对象的各个属性通常被用来存放应用的状态(state),所以我们可以通过监测一个 observable 达到监测应用状态的目的,创建一个 observable 的方法是给 MobX 的 observable 函数 传入一个对象(包括数组),例如:
const { observable } = require("mobx-miniprogram");
const myObservable = observable({ name: "kejiweixun" });
  • action:一段改变 state 的代码,比如上面的例子,如果我的网页中有一个按钮,点击该按钮会触发一个事件函数,该事件函数会改变 name 这个 state,那这个函数就是一个 action,myObservable.name = “keke” 也是一个 action,因为它也会改变 name,但最佳做法是使用 action 函数显式告诉 MobX 这段代码是一个 action,action 函数需要接收一个函数作为参数,即它只能把一个函数(可以是 async 函数)显式声明为 action,我们可以把 observable 对象中的 method 声明为 action(如果它改变了 state 的话),也可以把一个事件函数声明为对象;
const { observable, action } = require("mobx-miniprogram");
const state = observable({ value: 0 });
const increment = (state) => {
  state.value++;
};
//即使没有使用 action 函数,increment 也是一个 action,
//因为它修改了 observable,但建议总是使用 action 函数进行显式声明
const incrementAction = action(increment);
increment(state);
  • derivations:从 state 衍生出来的东西,分为:
    • Computed values:在 observable 对象中增加一个 getter,observable 函数会自动地把它处理成一个 computed value,computed values 需要是 pure function,它不应该改变任何 state,只是从 state 中生成新的值;
    • Reactions:类似 Computed values,但 Computed values 是产生一个新的值,而 reactions 是产生一个 side effect,例如把最新的 state 显示在屏幕上就是一个 side effect,对于 react,是通过 mobx-react 这个 MobX binding 实现 reaction 的,而对于微信小程序,则是开头提及的 mobx-miniprogram-bindings。我们还可以使用 autorun、reaction 执行自定义 reactions,autorun 常用来打印日志。

以上三个核心概念的关系可以通过下面这张图片理解:
在这里插入图片描述

在微信小程序中使用 Mobx

在微信小程序中使用 MobX 需要同时安装以下两个依赖,这在开头就说过了。第一个依赖其实是 MobX 官方项目的 fork,把它理解成 mobx 即可;第二个依赖是针对小程序的 binding,MobX 为多个 web 框架分别开发了对应的 binding,例如 React 的是 mobx-react,Vue 的是 mobx-vue。

  • mobx-miniprogram
  • mobx-miniprogram-bindings

构造一个小程序页面有两种方法,一种是使用 Page 构造器,另一种是使用 Component 构造器,这里只分享使用 Component 构造器构造页面时 mobx-miniprogram-bindings 的使用。以下是一个例子:

// store.js,在这个文件中创建一个 observable 对象
import { observable, action } from "mobx-miniprogram";
export const store = observable({
  // 数据字段
  numA: 1,
  numB: 2,
  // 计算属性,前面说过了,getter 会被 observable() 处理成一个 computed value
  get sum() {
    return this.numA + this.numB;
  },
  // actions,前面说过了,修改了数据字段的代码就是 action,需要用 action() 显式声明
  update: action(function () {
    const sum = this.sum;
    this.numA = this.numB;
    this.numB = sum;
  }),
});
//使用 Component 构造小程序页面,引入 storeBindingsBehavior,并增加 storeBindings 属性,该属性规定有 store、fields、actions 三个字段
import { storeBindingsBehavior } from "mobx-miniprogram-bindings";
import { store as myStore } from "./store.js";
Component({
  behaviors: [storeBindingsBehavior],
  storeBindings: {
    store: myStore, //使用 observable 函数创建的 observable 对象,常被叫做 store
    fields: ["numA", "numB", "sum"], //observable 对象中的数据属性、计算属性(getter)
    actions: ["update"], //observable 对象中的 action
  },
});

mobx-miniprogram-bindings 的核心是它 export 的 storeBindingsBehavior,它的作用主要有三个:

  • 处理 storeBindings.fields:当小程序页面进入页面节点树时,createDataFieldsReactions 函数会被调用,该函数会使用 MobX 的 reaction 函数创建一些自定义 reaction,这些自定义 reaction 的具体任务是看看 storeBindings.fields 中各字段的值是否发生了变化,如果变化了,就调用微信小程序的 this.setData() 把更新后的值渲染到页面;
  • 处理 storeBindings.actions:当页面引入该 storeBindingsBehavior 时,storeBindingsBehavior 中的 definitionFilter 函数会被执行,该函数会进一步调用 createActions 函数,从而把 observable 对象中相应的 action(例如代码示例中的 update)挂载到页面的 method 对象中,这样页面就可以这样触发该 action:this.update(),其实等同于 myStore.update();
  • storeBindingsBehavior 还定义了一个 detached 生命周期函数,其工作内容是:当页面从页面节点树移除时,给前面定义的所有 reaction 函数传入一个空参数,即执行 reaction(),从而避免内存泄漏。

总结一下,mobx-miniprogram-bindings 的核心是 storeBindingsBehavior,而 storeBindingsBehavior 的核心是 createDataFieldsReactions、createActions。顾名思义,createDataFieldsReactions 是为 storeBindings.fields 中的各字段创建自定义 reaction,createActions 是把 storeBindings.actions 中的各 action 函数挂载到页面下方便调用。

需要注意的是,storeBindings.actions 的各 action 会被挂载到页面的 this.methods 下,所以我们可以像 this.update() 这样调用它,而 storeBindings.fields 并没有被挂载到 this.data 下,但我们依然可以像 this.data.numA 这样访问它的值,为什么?这是因为 createDataFieldsReactions 函数所创建的 reaction 在调用 setData 时,会把值 set 到页面中同名的 data 字段中,比如 numA 这个 field 所对应的 reaction 会这样 setData:this.setData({numA: 1})。于是,页面本来是没有 this.data.numA 这个字段的,被这个 reaction 一番操作后,就多了这么一个字段。

createDataFieldsReactions 在创建一个 reaction 时,把 fireImmediately 设置为了 true,如果把它改为 false,在页面的 onload 函数的开头位置访问 this.data.numA 会得到 undefined,这充分证明了这个页面本来确实没有 this.data.numA,后来之所以有了,是被 reaction setData 上去的。

所以要注意了,我们不应该在页面的 js 文件中使用 setData 赋值给与 storeBindings.fields 同名的字段,正确的做法应该是使用 storeBindings.actions 修改 storeBindings.fields 字段的值,剩下的就交给 MobX,你可以相信 MobX 会把这个值渲染到界面中,如果这个值发生了变化的话。

MobX 的原则是:

Make sure that everything that can be derived from the application state, will be derived. Automatically.

这也应该是我们使用 MobX 的原则:定义最基本的 state,所有可以从这些 state 衍生出来的 computed value 或 reaction,都应该让 MobX 自动衍生,避免人为干预。所有修改 state 的函数或方法都应该显式声明为 action,我们只负责触发 action,剩下的都交给 MobX:action 触发会导致 state 发生改变,这进一步会导致 computed value 发生改变,以及 reaction 做出反应,这些都是由 MobX 自动进行的,交给 MobX 吧,我们只负责触发 action。

使用 MobX 容易让人产生困惑的一点是,如果一个 observable 对象的某个属性的值是一个对象(下方示例的 name),并且某个 action 被触发后只修改了该对象的某个属性(下方示例的 name.first),那 mobx-miniprogram-bindings 是不会把修改后的值渲染到界面中的。

示例代码:

!-- index.html -->
<view>First Name: {{name.first}}</view>
<view>Last Name: {{name.last}}</view>
<button bindtap="handleTap">点击更换 First Name</button>
//index.js
import { storeBindingsBehavior } from "mobx-miniprogram-bindings";
import { store } from "./store";

Component({
  behaviors: [storeBindingsBehavior],
  storeBindings: {
    store,
    fields: ["name"],
    actions: ["changeFirstName"],
  },

  methods: {
    handleTap: function () {
      this.changeFirstName("Williams");
    },
  },
});
//store.js
import { observable, action } from "mobx-miniprogram";

export const store = observable({
  name: {
    first: "Elon",
    last: "Musk",
  },
  changeFirstName: action(function (firstName) {
    //1、需要替换整个对象:
    this.name = Object.assign({}, this.name, { first: firstName });
    //2、只是更新 name 对象的某个属性,是不会引起界面变化的,如:
    //this.name.first = firstName;
  }),
});

这个例子表明,更改某个值为 object 的 state 时,不能只更改这个 state 的某个属性,而应该替换整个 state,否则不会引起界面变化。

总结

在微信小程序中使用 MobX,需要安装 mobx-miniprogram 和 mobx-miniprogram-bindings,接着在一个单独的 js 文件(通常命名为 store.js)中使用 MobX 下的 observable 函数创建一个 observable 对象,以用作存放应用状态的 store。

我们通常会在 observable 对象中定义一些数据属性、computed value、action。在小程序页面中,建议使用 Component 构造器构造页面,在页面增加 storeBindings 字段,并从 mobx-miniprogram-bindings 导出 storeBindingsBehavior,该 behavior 会依据 storeBindings.fields 创建相应的 MobX reaction,同时把 storeBindings.actions 挂载到页面的 this.methods 对象下。

当一个页面需要更新 store 中的某个 state 时,我们只需要触发相应的 action,剩下的都交给 MobX:action 会修改 state,state 的改变会引起 computed value 的自动更新,state 和 computed value 的改变都会引发 reaction,在小程序中,就是把更新后的值渲染到页面中展示。

需要特别注意的是,如果更新的 state 是一个对象,需要替换整个对象,如果只更新该对象的某个属性,是不会引起界面变化的。

摘录

https://kejiweixun.com/blog/how-to-use-mobx-in-wechat-miniprogram

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2098097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【全志H616】【开源】 ARM-Linux 智能分拣项目:阿里云、网络编程、图像识别

【全志H616】【开源】 ARM-Linux 智能分拣项目&#xff1a;阿里云、网络编程、图像识 文章目录 【全志H616】【开源】 ARM-Linux 智能分拣项目&#xff1a;阿里云、网络编程、图像识1、实现功能2、软件及所需环境3、逻辑流程图及简述3.1 完整逻辑流程图3.2 硬件接线3.3 功能简述…

【TomCat】安装部署

首先得进行Java的安装和部署java1.8对应tomcat9 TomCat下载Apache Tomcat - Apache Tomcat 10 Software Downloads

Vue(四) 组件、单文件组件、非单文件组件,重要的内置关系

文章目录 1. 组件2. 非单文件组件2.1 定义组件2.2 注册组件2.3 使用组件2.4 组件命名、标签等注意点2.5 组件嵌套2.6 VueComponent构造&#xff08;这部分看视频更易理解&#xff09;2.7 内置关系 3. 单文件组件 1. 组件 组件是实现局部功能代码和资源的集合 传统方式&#x…

unreal engine5.4.3动画重定向

UE5系列文章目录 文章目录 UE5系列文章目录前言 前言 ue5.4和ue3动画重定向之间存在差异&#xff0c;跟ue5.2差别更大一点&#xff0c;总之ue5.4越来越简化动画重定向&#xff0c;不想之前还需要制作RTG文件 这是ue5.3.2的制作动画重定向的界面 这是ue5.4.2的制作动画重定向…

华芯邦获AEC-Q车规级系列认证与AQG324认证的双重背书,碳化硅SiC-MOSFET半导体功率器件器件已在重点头部新能源汽车厂商模块验证中。

在获得AEC-Q车规级系列认证与AQG324认证的双重背书后&#xff0c;华芯邦的碳化硅SiC-MOSFET器件不仅巩固了其在新能源汽车领域的领先地位&#xff0c;更进一步加速了其在全球汽车供应链中的深度布局。这款车规级产品凭借其卓越的耐高温、低导通电阻及高开关频率等特性&#xff…

kubernetes里面那些事——————OpenEBS

OpenEBS存储 一&#xff0c;OpenEBS简介二&#xff0c;卷类型三&#xff0c;本地卷存储引擎类型四&#xff0c;复制卷存储引擎类型&#xff08;副本卷&#xff09;4.1 复制卷实现原理4.2 复制卷的优势 五&#xff0c;openebs存储引擎技术选型六&#xff0c;k8s中部署openebs服务…

项目延期,怎么有效调整计划,追赶进度

在项目管理过程中&#xff0c;项目延期是一个令人头疼但又无法完全避免的问题。无论是由内部因素还是外部因素导致&#xff0c;都会对项目的整体进度、成本和质量产生影响。 面对延期&#xff0c;关键在于如何迅速而有效地调整项目计划&#xff0c;以确保项目能够尽快回到正轨…

新版IDEA配置前进和后退、打开资源管理器等快捷按钮

新版IDEA&#xff0c;好像是IDEA2024版本开始就默认隐藏了工具条&#xff0c;这时一些很常用的快捷按钮&#xff0c;如前进、后退、打开资源管理器就无法使用。这里图文介绍&#xff0c;如何把这些配置出来。 具体操作如下&#xff1a; 1、选择 File / Settings(windows版)&am…

关于contextmenu-ui组件库

关于这个组件库把&#xff0c;主要用在个人博客制作中&#xff0c;而且由于作者很懒&#xff0c;已经一个多月没有更新了&#xff0c;甚至第二次更新都忘了修改md文件了。 这个组件库是使用vue3和TS来写的&#xff0c;关于引用&#xff0c;看这里 都有介绍的&#xff0c;直接…

计算机网络(八股文)

这里写目录标题 计算机网络一、网络分层模型1. TCP/IP四层架构和OSI七层架构⭐️⭐️⭐️⭐️⭐️2. 为什么网络要分层&#xff1f;⭐️⭐️⭐️3. 各层都有那些协议&#xff1f;⭐️⭐️⭐️⭐️ 二、HTTP【重要】1. http状态码&#xff1f;⭐️⭐️⭐️2. 从输入URL到页面展示…

边缘计算工业网关可以为工业企业生产提供哪些价值应用?天拓四方

在数字化、网络化、智能化高度融合的今天&#xff0c;工业领域正迎来一场深刻的变革。边缘计算工业网关&#xff0c;作为这场变革中的关键角色&#xff0c;以其强大的数据处理能力、高效的通信效率和灵活的部署方式&#xff0c;为智能制造注入了新的活力。本文将结合一个实际应…

【安卓13】解决HDMI OUT和耳机等设备接入时会解除静音问题

安卓原生定义了部分外部设备接入时是否静音&#xff0c;比如耳机、有线扬声器、HDMIOUT设备等&#xff0c;这些设备接入时&#xff0c;安卓会设置AudioSystem.STREAM_MUSIC为非静音状态 从代码里可以看出&#xff0c;当一个newDevice 接入时&#xff0c;会携带一个deviceID&am…

Java基于微信小程序的超市购物管理系统

1 简介 Java基于微信小程序的超市购物管理系统&#xff0c;此超市购物系统利用当下成熟完善的springboot框架&#xff0c;使用跨平台的可开发大型商业网站的Java语言&#xff0c;以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了收货地址管理、购物车管理、…

Win11 / Win10 系统极化工具,降低游戏延迟效果明显

Win11 / Win10 系统优化工具,降低游戏延迟效果明显 Windows 系统优化就是精简系统一些功能组件、对一些系统功能进行设置等&#xff0c;这样可以减少不必要的硬件资源占用。 全面的系统优化功能外&#xff0c;据不少网友表示通过优化后 CS GO 游戏降低输入延迟效果明显。 免费…

领夹麦克风哪个牌子音质好?西圣、博雅、枫笛领夹麦克风对比

当今的直播、短视频已经深深的融入到了我们的生活当中&#xff0c;很多小伙伴会通过拍摄短视频、Vlog来分享自己生活精彩的瞬间。不过录制视频时&#xff0c;如果单纯靠手机拾音会发现&#xff0c;音频效果是极差的&#xff0c;特别距离手机越远效果会越明显&#xff0c;会出现…

【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(二十二)

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

一文直接搞懂SpringMVC完整版教程

三、SpringMVC 1、SpringMVC简介 1.1、什么是MVC MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器来划分 M&#xff1a;Model&#xff0c;模型层&#xff0c;指工程中的JavaBean&#xff0c;作用是处理数据 JavaBean分为两类&#xff1a; 一类称为实体…

《黑神话悟空》广智打法技巧图文攻略详解

​黑神话悟空广智会挥舞火刀砍我们&#xff0c;是前期一个较难的boss&#xff0c;那么广智怎么打&#xff1f;基本就是别贪刀&#xff0c;躲技能&#xff0c;然后砍就完事儿了。这个boss之所以是第一个boss&#xff0c;可能就是锻炼大家躲技能的能力的&#xff0c;下面就来看下…

大数据测试知识架构与技术框架分享|大数据测试工程师学习方向

本文一起看一下关于大数据技术的基本的技术体系和典型技术栈&#xff0c;帮助想要从事大数据方向软件测试的朋友快速了解需要掌握的知识架构。 大数据基本的思想、它的整体框架&#xff0c;与以往的数据相关体系实际上是相类似的。区别主要在于数据的收集、存储包括资源的调度…