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

news/2024/9/18 2:13:21/ 标签: 微信小程序, 小程序

小程序>微信小程序官方在 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 valueget 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 对象,常被叫做 storefields: ["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.ppmy.cn/news/1518336.html

相关文章

Unity 中使用SQLite数据库

文章目录 0.参考文章1.Presentation —— 介绍2.&#xff08;SQLite4Unity3d&#xff09;Unity中直接使用SQLite的插件3.创建数据库4.创建表5.Navicat Premium&#xff08;数据库可视化&#xff09;6.增删改查6.1 增6.2 删6.3 改6.4 查 0.参考文章 https://blog.csdn.net/Chin…

查看特定软件网络请求信息

开始 运行 输入 wmic 再输入 process get ProcessId,executablepath 获取指定软件的 pid&#xff0c;例如获取的 pid 是 11008 再 开始 运行 输入cmd 输入 netstat -ano|findstr 11008 即可获取该程序的网络请求信息 参考 https://blog.csdn.net/zhangge360/article/detai…

微信小程序服务器费用一年多少?微信小程序开发

在互联网时代&#xff0c;微信小程序已成为众多企业和个人拓展业务、提升服务品质的有力工具。然而对于许多准备涉足小程序领域的朋友来说【开发一个小程序大概需要多少钱】以及【微信小程序服务器费用一年需要多少】是首要关注的问题&#xff0c;今天飞飞将和你们分享小程序服…

两个月冲刺软考——SQL基础:排序、分组和聚合函数的实用指南

1.涉及到的部分基本语法 1.1 ORDER BY 与 GROUP BY ORDER BY用于对查询结果进行排序&#xff1b;默认是升序&#xff08;ASC&#xff09;&#xff0c;可以指定降序&#xff08;DESC&#xff09;。 GROUP BY用于将数据按照一个或多个列进行分组&#xff1b;通常与聚合函数&am…

Mybatis框架——缓存(一级缓存,二级缓存)

本章将简单介绍Mybatis框架中的缓存&#xff0c;欢迎大家点赞➕收藏&#xff0c;蟹蟹&#xff01;&#xff01;&#xff01;&#x1f495; &#x1f308;个人主页&#xff1a;404_NOT_FOUND &#x1f308;MyBatis环境搭建步骤&#xff08;超全解析&#xff01;&#xff01;&am…

网络安全 DVWA通关指南 DVWA File Upload(文件上传)

DVWA File Upload&#xff08;文件上传&#xff09; 文章目录 DVWA File Upload&#xff08;文件上传&#xff09;修复建议 LowMediumHighImpossible 修复建议 1、使用白名单限制可以上传的文件扩展名 2、注意0x00截断攻击&#xff08;PHP更新到最新版本&#xff09; 3、对上传…

关键字之sizeof

接下来我讲的是之前我提到过的C语言关键字 sizeof同时它也是C语言提供的操作符&#xff08;运算符&#xff09; 它的使用形式有两种 1 sizeof&#xff08;类型&#xff09; 2 sizeof 表达式 sizeof返回某种数据类型或某个值占用的字节数量&#xff0c;它的参数可以是数据类型…

怎样通过bs4找出程序中 标签<div class=“List2“>中所有的<li>的内容?

怎样通过bs4找出程序中 标签<div class"List2">中所有的<li>的内容&#xff1f; 可以使用 BeautifulSoup 的 find_all 方法来找到标签为 <div class"List2"> 中的所有 <li> 标签&#xff0c;并获取其内容。 以下是一个示例代码&…

【面试经验】美团基础研发部产品经理面试经验

3.12 投递 4.1 一面 4.11 二面 4.17 oc但拒 一面内容&#xff1a; 1、一个指数增长的脑经急转弯 2、对向量和向量值如何理解 ——类比函数&#xff0c;目的是映射和转化 3、transformer有没有看&#xff08;问到了注意力机制&#xff09; ——transformer的本质是一个编码…

http连接处理

分析http类及请求接收 基础 epoll epoll_create函数 #include <sys/epoll.h> int epoll_create(int size) 创建一个指示epoll内核事件表的文件描述符&#xff0c;该描述符将用作其他epoll系统调用的第一个参数&#xff0c;size不起作用。 epoll_ctl函数 #include …

基于Python的热门旅游景点数据分析系统【python-爬虫-大数据定制】

&#x1f496;&#x1f525;作者主页&#xff1a;毕设木哥 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; 实战项目 文章目录 实战项目 一、基于Python的热门旅游景点数…

sheng的学习笔记-AI-半监督聚类

AI目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 半监督学习&#xff1a;sheng的学习笔记-AI-半监督学习-CSDN博客 聚类&#xff1a;sheng的学习笔记-AI-聚类(Clustering)-CSDN博客 均值算法&#xff1a;sheng的学习笔记-AI-K均值算法_k均值算法怎么算迭代两次后的最大…

论文阅读:VideoMamba: State Space Model for Efficient Video Understanding

论文地址&#xff1a;arxiv 摘要 为了解决视频理解中的局部冗余与全局依赖性的双重挑战。作者将 Mamba 模型应用于视频领域。所提出的 VideoMamba 克服了现有的 3D 卷积神经网络与视频 Transformer 的局限性。 经过广泛的评估提示了 VideoMamba 的能力&#xff1a; 在视觉领…

Zookeeper 日志输出到指定文件夹,并按照日期轮循输出

更改日志输出路径 如果不做修改&#xff0c;zookeeper的日志信息默认都打印到了zookeeper.out文件中&#xff0c;这样输出路径和大小没法控制&#xff0c;因为日志文件没有轮转。所以需要修改日志输出方式。具体操作如下&#xff1a; 1.修改${zkhome}/bin/zkEnv.sh ZOO_LOG_…

我的推荐:腾讯云罗云《从零构建向量数据库》

在2024年8月&#xff0c;好几本和数据库相关的图书相继出版&#xff0c;我以为&#xff0c;这恰恰是数据库领域蓬勃向上的一种表现。 数据库需要更多的人关注&#xff0c;哪怕是谈论&#xff0c;所以我的《数据库简史》是一种尝试&#xff0c;希望以一种科普的风格&#xff0c;…

信息安全数学基础(4)最大公因数

前言 在信息安全数学基础中&#xff0c;最大公因数&#xff08;Greatest Common Divisor, GCD&#xff09;是一个核心概念&#xff0c;它在密码学、数论等多个领域都有广泛应用。以下是对最大公因数的详细阐述&#xff1a; 一、定义 设a和b是两个非零整数&#xff0c;若整数d同…

框架 +【Mybatis】概述 以及 基础环境搭建

目录 什么是框架&#xff1f; java后端框架包括 Mybatis概述 1、背景介绍 2、mybatis介绍 Mybatis环境搭建 1.创建一个maven项目 2.导入mysql数据库驱动包 导入mybatis依赖的jar包 3.创建一个全局的mybatis配置文件 4.创建数据库,创建表,准备数据 5.创建一个访问接口…

PHP一体化解决方案高效整合与优化学校管理系统小程序源码

一体化解决方案&#xff0c;让学校管理系统焕发新生✨ &#x1f3eb; 开篇&#xff1a;传统管理的瓶颈与挑战 在快节奏的教育时代&#xff0c;传统的学校管理系统是否让你感到力不从心&#xff1f;&#x1f914; 信息孤岛、流程繁琐、效率低下...这些问题是否正困扰着你的工作…

vue 使用el-table 设置了show-overflow-tooltip属性,路由跳转后,气泡不消失的解决办法

文章目录 一、问题场景二、解决方法1.问题bug2.最终解决 总结 一、问题场景 在vue项目里使用el-table做一个列表页面&#xff0c;表格设置了show-overflow-tooltip属性&#xff0c;文字过长时鼠标滑过会展示气泡显示全部文字内容&#xff0c;因为设置路由缓存&#xff0c;如果…

哈苏相机SD卡数据恢复指南:从格式化到重生

在摄影的世界里&#xff0c;‌哈苏相机以其卓越的画质和精湛的工艺赢得了无数摄影师的青睐。‌然而&#xff0c;‌面对不慎的误操作&#xff0c;‌如SD卡格式化&#xff0c;‌珍贵的照片和视频数据可能瞬间消失&#xff0c;‌这无疑是对摄影师的重大打击。‌本文将深入探讨如何…