mobx学习笔记

mobx介绍

  • mobx是一个功能强大,上手容易的状态管理工具。
  • MobX背后的哲学很简单:任何源自应用状态的东西都应该自动地获得。
  • 利用getter和setter来收集组件的数据依赖关系,从而在数据发生变化的时候精确知道哪些组件需要重绘。

mobx和redux的区别

  • mobx更趋向于面向对象编程(OOP)
  • 对一份数据直接进行修改操作,不需要始终返回一个新的数据
  • 并非单一store,可以多store
  • redux默认以javascript原生对象形式存储数据,而mobx使用的是可观察对象

优缺点

优点
  • 学习成本小
  • 面向对象编程,对TS友好
缺点
  • mobx过于自由,提供的约束和模板代码很少,代码编写自由,如果不做一些约定,比较容易导致团队代码风格不同一
  • 相关的中间件很少,逻辑层业务整合是问题

mobx原则

MobX 支持单向数据流,也就是动作改变状态,而状态的改变会更新所有受影响的视图。
在这里插入图片描述
当状态改变时,所有衍生都会进行原子级的自动更新。因此永远不可能观察到中间值。
所有衍生默认都是同步更新。这意味着例如动作可以在改变状态之后直接可以安全地检查计算值。

mobx安装

yarn add -D mobx mobx-react

mobx的简单使用

import {observable,autorun} from 'mobx'

observable负责将数据转换为可观察的对象或者数组,
每次改数据时,就会在autorun的回调函数中触发,autorun相当于监听者。

对于普通数据的监听
// 对于普通数据的监听
let observableGender = observable.box('男');
// 监听变化(第一次必须执行,之后每次改变也会执行)
autorun(() => {console.log('observableNumber: ', observableGender.get());
});
// 设置
setTimeout(() => {observableGender.set('女');
}, 1000);

组件第一次渲染时,autorun会自动执行一次,如上例,以后每次相关可观察值改变,都会打印1次。

注意,在vconsole中可以看到mobx警告。
[MobX] Since strict-mode is enabled, changing (observed) observable values without using an action is not allowed
在这里插入图片描述
mobx由于启用了严格模式,因此不允许在不使用action的情况下直接更改(观察到)值。异步的函数不能直接更改数据。
要更改可观察值,需要通过action触发。

对于对象的监听
// 对于对象的监听-------
let observableObj = observable.map({name: 'wuqing',age: 30,
});
autorun(() => {console.log('observableObj对象属性name:', observableObj.get('name'));
});
setTimeout(() => {// 只会打印1次,autorun只会监听与其相关的属性// observableObj.set('age', 100);observableObj.set('name', 'wuqing1');
}, 3000);

autorun只会监听与其相关的属性
对象监听另外一种写法:

let observableObj = observable({name: 'wuqing',age: 30,
});
autorun(() => {console.log('observableObj对象属性name:', observableObj.name);
});
setTimeout(() => {observableObj.name="wuqing1";
}, 3000);
为了代码风格统一,可以开启严格模式。

配置enforceActions: ‘always’,等于开启严格模式,必须用action触发数据更新。
若配置never,则不会启用。

import { observable, configure } from 'mobx';// 严格模式
configure({enforceActions: 'always',
});const store = observable({showMessage: false,name: '张伟',
});export default store;

配置严格模式后,若不通过action直接修改store数据,会报错 Since strict-mode is enabled, changing (observed) observable values without using an action is not allowed.

严格模式默认应该是开启的。

可观察值只允许通过action方法改,不能直接改
import { observable, configure, action } from 'mobx';
// 严格模式
configure({enforceActions: 'always',
});
const store = observable({showMessage: false,name: '张伟',changeNameAction() {// 可观察值name的方法this.name = '刘德华';},},{changeNameAction: action, // 标记action是用于专门修改可观察值name的方法}
);
export default store;

上面换一种写法,用ES7注解器的写法是:
@observable和@action都是装饰器,通俗来说装饰器是将传入的值或者函数进行处理从而返回更加强大的值或者函数。

class Store {@observable name = '张伟';@observable showMessage = false;@action changeNameAction() {// 可观察值name的方法this.name = '刘德华' + Math.random();console.log('aaaa-->', this.name);}
}// 单例模式,无论谁导入,都是同一个对象
const store = new Store();export default store;

到这里,会发现react如果没有经过配置,直接使用decorators装饰器语法会报错,
在这里插入图片描述
Support for the experimental syntax ‘decorators’ isn’t currently enabled
因为react默认是不支持装饰器语法,需要做一些配置来启用装饰器语法。

step1:

在 tsconfig.json 中启用编译器选项 “experimentalDecorators”: true
vscode点击设置,输入搜索experimentalDecorators
在这里插入图片描述

step2:

安装支持修饰器所需依赖。

yarn add -D @babel/core @babel/plugin-proposal-decorators @babel/preset-env

创建.babelrc文件,配置

{"presets": ["@babel/preset-env"],"plugins": [["@babel/plugin-proposal-decorators",{"legacy": true}]]
}
step3:

安装依赖

yarn add -D customize-cra react-app-rewired

在项目根目录下创建 config-overrides.js 并写入以下内容,覆盖默认配置。

const path = require('path')
const { override, addDecoratorsLegacy } = require('customize-cra')function resolve(dir) {return path.join(__dirname, dir)
}const customize = () => (config, env) => {config.resolve.alias['@'] = resolve('src')if (env === 'production') {config.externals = {'react': 'React','react-dom': 'ReactDOM'}}return config
};
module.exports = override(addDecoratorsLegacy(), customize())
step4:

修改package.json文件中 scripts 脚本。

"scripts": {"start": "react-app-rewired start","build": "react-app-rewired build","test": "react-app-rewired test","eject": "react-scripts eject"}

上面4个步骤配置完成后,如果mobx修饰器还是不起作用,就可能是mobx版本有问题,执行step5。

step5:

执行下面命令

yarn add -D mobx@5 mobx-react@5

执行到step5,就能成功使用mobx修饰器了。

注意,如果报错
Parsing error: Cannot use the decorators and decorators-legacy plugin together
在这里插入图片描述
可以创建.eslintrc.js文件,配置即可解决eslint报错问题

parserOptions: {parser: 'babel-eslint',ecmaFeatures: {// 支持装饰器legacyDecorators: true,},},

在这里插入图片描述

mobx核心API介绍

observable: observable是将类属性等进行标记,实现对其的观察。
actions:动作,通过action改变state。action函数是对传入的function进行一次包装,使得function中的observable对象的变化能够被观察到,从而触发相应的衍生。
autoRun:当你想创建一个响应式函数,但是该函数永远没有观察者,此时使用autorun。这通常是当你需要从反应式代码桥接到命令式代码的情况,例如打印日志、持久化或者更新UI的代码。
当使用 autorun 时,所提供的函数总是立即被触发一次,然后每次它的依赖关系改变时会再次被触发。
相比之下,computed(function) 创建的函数只有当它有自己的观察者时才会重新计算,否则它的值会被认为是不相关的。 经验法则:如果你有一个函数应该自动运行,但不会产生一个新的值,请使用autorun。 其余情况都应该使用 computed。
装饰器
runInAction:工具函数,是创建异步action的一种方式。
action只会对当前包装/装饰的函数做出反应,而不会对当前运行函数所调用的函数(不包含在当前函数之内)作出反应!这意味着如果 action 中存在 setTimeout、promise 的 then 或 async 语句,并且在回调函数中某些状态改变了,那么这些回调函数也应该包装在 action 中。
@observable
定义 state
@computed
可以定义在相关数据发生变化时自动更新的值,像这样的计算可以类似于 MS Excel 这样电子表格程序中的公式。每当只有在需要它们的时候,它们才会自动更新。
@action
定义操作 state 的方法。
@observer
用来将 React 组件转变成响应式组件。observer 是由单独的 mobx-react 包提供的。
@inject
将组件连接到提供的 stores。
mobx-react 包还提供了 Provider 组件,它使用了 React 的上下文(context)机制,可以用来向下传递 stores。 要连接到这些 stores,需要传递一个 stores 名称的列表给 inject,这使得 stores 可以作为组件的 props 使用。

使用

新建store.js,封装Store Class专门用于状态管理,再export Store的实例对象store。

import { action, configure, observable, runInAction } from 'mobx';
// 严格模式
configure({enforceActions: 'always',
});
class Store {@observable name = '张伟';@observable showMessage = false;@observable messageList = [];@action changeNameAction() {// 可观察值name的方法this.name = '刘德华' + Math.random();}@action async getMessageList() {const datas = await getMessageListApi();// 异步runInAction(()=>{this.messageList=datas})}
}
// 单例模式,无论谁导入,都是同一个对象
const store = new Store();export default store;function getMessageListApi() {return new Promise((resolve) => {return setTimeout(() => {const list = [];for (let i = 0; i < 5; i++) {list.push(`MSG-${Math.random()}`);}resolve(list);}, 1500);});
}

从mobx-react中引入Provider,全局注册并注入store实例,内部组件就能使用到store中的state

import { Provider } from 'mobx-react';
import store from './mobx-demo/Store/store-1';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(// store属性名自命名,为了区别,写了一个demo名<Provider demoStore={store}><App /></Provider>
);

内部组件需要使用state时,先要用@inject装饰器注入store,再用@observer将组件标记为 observer,当组件中使用到的store state发生变化时,组件会自动响应更新。

@inject("demoStore") // 通过inject修饰器注入store
@observer
export default class App extends Component {componentDidMount() {console.log('name-->', this.props.demoStore.name);}render() {return <RouterProvider router={routes}></RouterProvider>;}
}

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

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

相关文章

【机器学习】独立成分分析(ICA):解锁信号的隐秘面纱

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 独立成分分析&#xff08;ICA&#xff09;&#xff1a;解锁信号的隐秘面纱引言I…

免杀笔记 ---> APC注入

除了我们前面讲的DLL注入&#xff0c;还有一个APC注入的东西也是很重要的&#xff01;&#xff01; &#xff1a;&#xff1a;确实很重要&#xff0c;相应的&#xff0c;在跟新完今天的代码之后&#xff0c;我也会对应的进行Github上工具的更新&#xff01;&#xff01; 1.AP…

css实现3d照片墙

效果图 vue2写法&#xff1a; <template><div class"container"><div class"box"><div class"circle circle1"><img src"../../../assets/images/main/logo.png" alt"" /></div>&l…

实战教程:如何利用Optimizer优化你的Windows系统?

前言 你是否厌倦了系统臃肿、隐私泄露的烦恼&#xff1f;小江湖今天就要带你走进一个全新的世界&#xff0c;一个能够让你重获自由与安心的神奇之地——Optimizer&#xff0c;一款专为Windows用户打造的深度优化神器&#xff1b;有了它你仅需轻轻一点&#xff0c;再也不用为系…

p13 数组

数组的创建 数组是一组相同类型元素的集合。数组的创建方式&#xff1a; type_t arr_name [const_n]; //type_t 是指数组的元素类型 //const_n 是一个常量表达式&#xff0c;用来指定数组的大小 int main() {//创建一个数字组-存放整型-10个int arr[10]{1,2,3}//不完全初始…

TensorFlow系列:第四讲:MobileNetV2实战

一. 加载数据集 编写工具类&#xff0c;实现数据集的加载 import keras""" 加载数据集工具类 """class DatasetLoader:def __init__(self, path_url, image_size(224, 224), batch_size32, class_modecategorical):self.path_url path_urlself…

物联网系统中市电电量计量方案(一)

为什么要进行电量计量&#xff1f; 节约资源&#xff1a;电量计量可以帮助人们控制用电量&#xff0c;从而达到节约资源的目的。在当前严峻的资源供应形势下&#xff0c;节约能源是我们应该重视的问题。合理计费&#xff1a;电表可以帮助公共事业单位进行合理计费&#xff0c;…

3.相机标定原理及代码实现(opencv)

1.相机标定原理 相机参数的确定过程就叫做相机标定。 1.1 四大坐标系及关系 &#xff08;1&#xff09;像素坐标系&#xff08;单位&#xff1a;像素&#xff08;pixel&#xff09;&#xff09; 像素坐标系是指相机拍到的图片的坐标系&#xff0c;以图片的左上角为坐标原点&a…

为校园后勤注入智慧:收件登记功能驱动全新体验

在智慧校园的后勤管理体系中&#xff0c;收件登记服务是一项旨在提升快递接收体验的创新举措&#xff0c;它无缝融合了现代科技与日常校园生活&#xff0c;为师生带来便捷与安心。 为应对日益增长的快递需求&#xff0c;师生可事先通过校园网平台或特制的移动应用预报快递信息&…

光学传感器图像处理流程(二)

光学传感器图像处理流程&#xff08;二&#xff09; 2.4. 图像增强2.4.1. 彩色合成2.4.2 直方图变换2.4.3. 密度分割2.4.4. 图像间运算2.4.5. 邻域增强2.4.6. 主成分分析2.4.7. 图像融合 2.5. 裁剪与镶嵌2.5.1. 图像裁剪2.5.2. 图像镶嵌 2.6. 遥感信息提取2.6.1. 目视解译2.6.2…

数字化时代的供应链管理综合解决方案

目录 引言背景与意义供应链管理综合解决方案的目标 &#x1f4c4;供应链管理系统主要功能系统优势 &#x1f4c4;物流管理系统主要功能系统优势 &#x1f4c4;订单管理系统主要功能应用场景 &#x1f4c4;仓储管理系统系统亮点主要功能系统优势 &#x1f4c4;商城管理系统主要功…

【python】QWidget父子关系,控件显示优先级原理剖析与应用实战演练

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

又是三道简单的web题(2)

一、cookie 1.打开后是如下页面&#xff0c;抓包&#xff0c;关注cookie 2.发现cookie中有一个文件 3.直接访问这个文件&#xff0c;得到flag 二、employeeswork 打开后页面如下&#xff1a; 点击后出现一串php代码 审一下这个代码&#xff0c;需要添加参数work并且赋值work…

Linux笔记之使用系统调用sendfile高速拷贝文件

Linux笔记之使用系统调用sendfile高速拷贝文件 code review! 文章目录 Linux笔记之使用系统调用sendfile高速拷贝文件sendfile 性能优势sendfile 系统调用优点&#xff1a;缺点&#xff1a; cp 命令优点&#xff1a;缺点&#xff1a; 实际测试&#xff1a;拷贝5.8个G的文件&a…

合合信息大模型加速器亮相WAIC大会:文档解析与文本识别新突破

合合信息大模型加速器亮相WAIC大会&#xff1a;文档解析与文本识别新突破 文章目录 合合信息大模型加速器亮相WAIC大会&#xff1a;文档解析与文本识别新突破前言合合信息TextIn平台&#xff1a;智能文档处理的领军者文档解析引擎&#xff1a;百页文档秒级处理大模型的发展背景…

【漏洞复现】Crocus系统——Download——文件读取

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 Crocus系统旨在利用人工智能、高清视频、大数据和自动驾驶技术&…

工程化-vue3+ts:代码检测工具 ESLint

一、理解ESLint ESLint是一个开源的JavaScript代码检查工具&#xff0c;用于帮助开发人员规范和统一编码风格。它可以检查代码中的潜在错误、不一致的编码习惯以及一些常见的代码问题。 ESLint使用基于规则的插件体系&#xff0c;可以根据项目的需求和个人的偏好配置不同的规…

数据库数据恢复—SQL Server数据库由于存放空间不足报错的数据恢复案例

SQL Server数据库数据恢复环境&#xff1a; 某品牌服务器存储中有两组raid5磁盘阵列。操作系统层面跑着SQL Server数据库&#xff0c;SQL Server数据库存放在D盘分区中。 SQL Server数据库故障&#xff1a; 存放SQL Server数据库的D盘分区容量不足&#xff0c;管理员在E盘中生…

MacOS如何切换shell类型

切换 shell 类型 如果你想在不同的 shell 之间切换&#xff0c;以探索它们的不同之处&#xff0c;或者因为你知道自己需要其中的一个或另一个&#xff0c;可以使用如下命令&#xff1a; 切换到 bash chsh -s $(which bash)切换到 zsh chsh -s $(which zsh)$()语法的作用是运…