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>;
  }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【安全设备】APT攻击预警平台

一、什么是APT 高级持续性威胁&#xff08;APT&#xff09;是一种高度复杂和长期的网络攻击&#xff0c;旨在通过持续监视和访问特定目标来窃取敏感信息或进行其他恶意活动。这种攻击结合了多种先进的技术手段和社会工程学方法&#xff0c;以极高的隐蔽性实现长期潜伏和信息窃…

【排序算法】计数排序

目录 一.基本思想 二.缺陷及优化 三.代码实现 四.特性总结 1.可以排序负数 2.适合范围集中的整数 3.时间复杂度&#xff1a;O(Nrange) 4.空间复杂度&#xff1a;O(range) 5.稳定性&#xff1a;稳定 一.基本思想 根据待排序数组a创建一个新的数组count&#xff0c;该数组…

无人机之遥控器保养

一、使用存放 1、避免让遥控器受到强烈的震动或从高处跌落&#xff0c;以免影响内部结构的精度&#xff1b; 2、遥控器在使用完后&#xff0c;需要将天线收拢&#xff0c;避免折断&#xff0c;养成定期检查天线的习惯&#xff1b; 3、定期检查遥控器按键有无裂纹、畸变、松旷…

代码随想录算法训练营Day36||动态规划part04

494.目标和&#xff1a;本题的方法主要用来解决------装满容量为x的背包&#xff0c;有几种方法。 可以先理解二维数组的思路&#xff1a;感觉b站一个评论写得很清晰&#xff0c;借用一下。 这题最难理解的地方在于如何初始化数组&#xff0c;为什么dp[0]1&#xff1b;我试图自…

Visual Studio 2019 (VS2019) 中使用 CMake 配置 OpenCV 库(快捷版)

2024.07.11 测试有效 最近需要用一下 opencv 处理图像&#xff0c;简单配置了一下Cmake下的 opencv 库。 没有编译 opencv &#xff0c;也不知道他们为什么要自己编译 opencv 。 一、下载并安装 OpenCV 1.前往 OpenCV 官方网站 下载适用于您的系统的 OpenCV 安装包。 2.点击直接…

商品分类左右联动

1、先看效果 2、以hooks方法处理&#xff0c;方便复制使用&#xff0c;见代码 Good.vue文件 <script setup lang"ts" name"goods">import {onMounted, ref, nextTick} from "vue";import useProductScroll from "/utils/hooks/useP…

记一次若依框架和Springboot常见报错的实战漏洞挖掘

目录 前言 本次测实战利用图​ 1.判段系统框架 2.登录页面功能点测试 2.1 弱口令 2.2 webpack泄露信息判断 2.3 未授权接口信息发现 3.进一步测试发现新的若依测试点 3.1 默认弱口令 3.2 历史漏洞 4.访问8080端口发现spring经典爆粗 4.1 druid弱口令 4.2 SwaggerU…

【JavaScript 报错】未捕获的类型错误:Uncaught TypeError

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、错误原因分析1. 调用不存在的方法2. 访问未定义的属性3. 数据类型不匹配4. 函数参数类型不匹配 二、解决方案1. 检查方法和属性是否存在2. 使用可选链操作符3. 数据类型验证4. 函数参数类型检查 三、实例讲解四、总结 在…

I 2U-Net:具有丰富信息交互的双路径 U-Net 用于医学图像分割| 文献速递-基于深度学习的多模态数据分析与生存分析

Title 题目 I 2U-Net: A dual-path U-Net with rich information interaction for medical image segmentation I 2U-Net&#xff1a;具有丰富信息交互的双路径 U-Net 用于医学图像分割 01 文献速递介绍 在计算机视觉领域&#xff0c;医学图像分割是一个主要挑战&#xff…

电脑录音如何操作?电脑麦克风声音一起录制,分享7款录音软件

电脑录音已经成为我们日常生活和工作中不可或缺的一部分。无论是录制会议、教学、音乐、网络直播、音源采集还是其他声音&#xff0c;电脑录音软件都为我们提供了极大的便利。本文将为大家介绍如何操作电脑录音&#xff0c;并分享七款录音软件&#xff0c;包括是否收费、具体操…

给后台写了一个优雅的自定义风格的数据日志上报页面

highlight: atelier-cave-dark 查看后台数据日志是非常常见的场景,经常看到后台的小伙伴从服务器日志复制一段json数据字符串,然后找一个JSON工具网页打开,在线JSON格式化校验。有的时候,一些业务需要展示mqtt或者socket的实时信息展示,如果不做任何修改直接展示一串字符…

操作系统——内存管理(面试准备)

虚拟内存 单片机没有操作系统&#xff0c;每次写完代码&#xff0c;都需要借助工具把程序烧录进去&#xff0c;这样程序才能跑起来。 另外&#xff0c;单片机的CPU是直接操作内存的物理地址。 在这种情况下&#xff0c;想在内存中同时运行两个程序是不可能的&#xff0c;如果第…

ArduPilot开源飞控之AP_Mount_Servo

ArduPilot开源飞控之AP_Mount_Servo 1. 源由2. 框架设计2.1 公有成员2.2 受保护成员私有成员: 3. 重要方法3.1 AP_Mount_Servo::init3.2 AP_Mount_Servo::update3.3 AP_Mount_Servo::has_roll_control3.4 AP_Mount_Servo::has_pitch_control3.5 AP_Mount_Servo::has_pan_contro…

数据结构——查找算法

文章目录 1. 查找算法 2. 顺序查找 2. 二分查找 1. 查找算法 查找算法是用于在数据集中定位特定元素的位置的算法。查找是计算机科学中一项基本操作&#xff0c;几乎在所有应用程序中都需要使用。例如&#xff0c;数据库查询、信息检索、字典查找等都涉及到查找操作。查找算…

我们水冷电阻器支持高脉冲负载和高抗振能

我们电阻器是液冷电阻器&#xff0c;与风冷型电阻器相比&#xff0c;尺寸非常小。它们支持高脉冲负载和高抗振能力。 水冷电阻器具有完全绝缘的铝制外壳&#xff0c;带有液体冷却通道。主要的电阻元件是由厚膜浆料制成&#xff0c;具有低热漂移和出色的电阻精度。电阻元件嵌入氧…

Docker部署gitlab私有仓库后查看root默认密码以及修改external_url路径和端口的方法

文章目录 1、docker部署最新版gitlab2、进入gitlab容器3、修改路径地址ip和端口4、检验效果 1、docker部署最新版gitlab #docker安装命令 docker run --detach \--name gitlab \--restart always \-p 1080:80 \-p 10443:443 \-p 1022:22 \-v /gitlab/config:/etc/gitlab \-v …

人工智能算法工程师(中级)课程10-PyTorch神经网络之卷积神经网络与代码详解

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能算法工程师(中级)课程10-PyTorch神经网络之卷积神经网络实战与代码详解。卷积神经网络&#xff08;CNN&#xff09;是一种广泛应用于图像识别、目标检测、视频分析等领域的深度学习模型。本文将详细介绍卷积…

【VIVADO SDK调试遇到DataAbortHandler】

问题 SDK调试遇到DataAbortHandler问题。 运行后不显示结果&#xff0c;debug模式下发现进入DataAbortHandler异常函数。程序中存在大数组。 原因:SDK默认的堆栈为1024bytes,需要将堆栈调大。 修改方法&#xff1a; 解决:对application中src下的lscript.ld双击&#xff0c;…

【游戏引擎之路】登神长阶(七)——x86汇编学习:凡做难事,必有所得

5月20日-6月4日&#xff1a;攻克2D物理引擎。 6月4日-6月13日&#xff1a;攻克《3D数学基础》。 6月13日-6月20日&#xff1a;攻克《3D图形教程》。 6月21日-6月22日&#xff1a;攻克《Raycasting游戏教程》。 6月23日-7月1日&#xff1a;攻克《Windows游戏编程大师技巧》。 7月…

解决GET请求中文乱码问题

解决GET请求中文乱码问题 1、乱码的根本原因2、解决方法方法一&#xff1a;修改Tomcat配置&#xff08;推荐&#xff09;方法二&#xff1a;使用URLEncoder和URLDecoder&#xff08;不推荐用于GET请求乱码&#xff09;方法三&#xff1a;String类编解码&#xff08;不直接解决乱…