mobx学习笔记

news2024/9/21 11:01:44

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.coloradmin.cn/o/1916374.html

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

相关文章

javaweb学习day1《HTML篇》--新浪微博(前端页面的创建思路及其HTML、css代码详解)

一、前言 本篇章为javaweb的开端&#xff0c;也是第一篇综合案例&#xff0c;小编也是看着黑马程序员的视频对里面的知识点进行理解&#xff0c;然后自己找一个新浪微博网页看着做的&#xff0c;主要还是因为懒&#xff0c;不想去领黑马程序员的资料了。 小编任务javaweb和ja…

人工智能算法工程师(中级)课程6-sklearn机器学习之聚类问题与代码详解

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能算法工程师(中级)课程6-sklearn机器学习之聚类问题与代码详解。在机器学习领域&#xff0c;聚类是一种无监督学习方法&#xff0c;旨在将相似的数据点划分为同一类别。sklearn是一个广泛应用于机器学习的Py…

初识C++语言(1)

目录 C语言简介 C 语言概述 C 语言的特点 语言简洁紧凑&#xff0c;使用灵活方便 运算符丰富 数据结构丰富 结构化语言 生成的代码质量高 可移植性强 C程序结构 C语言系统的使用 一.启动Dev-C 二、新建源程序 三…

【观察】甲骨文:用“SQL”实现AI的“融会贯通”,打通应用落地的“最后一公里”...

从2022年的ChatGPT&#xff0c;到2024年的Sora&#xff0c;生成式AI和大模型技术正以不可思议的发展速度颠覆着我们的认知。刚刚过去的一年&#xff0c;国内的“百模大战”更让大模型站上了市场“风口”&#xff0c;通过更为泛化的能力&#xff0c;赋予了千行万业数智化无限的想…

ChatGPT提问获取高质量答案的艺术PDF下载书籍推荐分享

ChatGPT高质量prompt技巧分享pdf&#xff0c; ChatGPT提问获取高质量答案的艺术pdf。本书是一本全面的指南&#xff0c;介绍了各种 Prompt 技术的理解和利用&#xff0c;用于从 ChatGPTmiki sharing中生成高质量的答案。我们将探讨如何使用不同的 Prompt 工程技术来实现不同的目…

aws sap认证考试如何轻松通过

如何高效备考AWS SAP (Solutions Architect Professional) 认证? AWS SAP认证是AWS认证体系中难度最高的认证之一,要通过这个考试确实需要下一番功夫。但通过合理规划和有效准备,你可以提高通过的几率。以下是一些建议: 评估起点 首先诚实地评估自己的AWS知识水平和实践经验。…

聚鼎科技:装饰画未来前景好不好

在这个快速变化的时代&#xff0c;装饰画作为家居装饰和艺术表达的一种形式&#xff0c;其未来前景备受各界关注。随着人们审美的多元化和居住环境的个性化需求增长&#xff0c;装饰画逐渐从传统领域延伸到更加广阔的生活空间。 装饰画的市场潜力不容小觑。现代社会对美的追求日…

重塑肌肤DNA!华贝甄选解锁生命活力密码

在探索生命奥秘与健康的征途中&#xff0c;华贝甄选携手前沿干细胞科技&#xff0c;为您开启一场前所未有的健康革命。我们深知&#xff0c;生命的活力源自细胞的不懈更新与修复&#xff0c;而干细胞&#xff0c;正是这场生命奇迹的钥匙。 【重塑内分泌平衡&#xff0c;焕发自…

spring boot的学习--Springboot的Web开发(3)

1. 简介 1.1 创建springboot应用,选中我们需要的模块 1.2 springBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来 1.3 自己编写业务代码 顺便回顾下上一篇的自动装配 这个场景SpringBoot帮我们配置了什么&#xff1f;能不能修改&#xff1f;能修…

vue 搭建 pinia

文章目录 环境设置存储读取数据【 storeToRefs】借助storeToRefs将store中的数据转为ref对象&#xff0c;方便在模板中使用【getters】当state中的数据&#xff0c;需要经过处理后再使用时&#xff0c;可以使用getters配置【$subscribe】通过 store 的 $subscribe() 方法侦听 s…

韦尔股份:深蹲起跳?

利润大增7倍&#xff0c;是反转信号还是回光返照&#xff1f; 今天我们聊聊光学半导体龙头——韦尔股份。 上周末&#xff0c;韦尔股份发布半年业绩预告&#xff0c;预计上半年净利润13至14亿&#xff0c;同比增幅高达 754%至 819%。 然而&#xff0c;回首 2023 年它的净利仅 …

代码随想录算法训练营第二十九天

452. 用最少数量的箭引爆气球 这道题目我原本的想法是只要当前的气球半径范围在已有的箭头能够击穿的气球半径内就可以实现 但是 箭射出去的地方是一个值 而不是一个范围 因此有相同的重叠范围的许多气球并一定都有相同的值&#xff0c;因此这种方法不可取 这题的主要局部最…

『Django』自带的后台

theme: smartblue 本文简介 点赞 关注 收藏 学会了 上一篇讲了 Django 操作 MySQL 的方法&#xff0c;讲了如何创建模型&#xff0c;如何对数据库做增删改查的操作。但每次修改数据都要写代码&#xff0c;多少有点麻烦。 有没有简单一点的方法呢&#xff1f; 有的有的&#…

kotlin Flow 学习指南 (三)最终篇

目录 前言Flow生命周期StateFlow 替代LiveDataSharedFlow其他常见应用场景处理复杂、耗时逻辑存在依赖关系的接口请求组合多个接口的数据 Flow使用注意事项总结 前言 前面两篇文章&#xff0c;介绍了Flow是什么&#xff0c;如何使用&#xff0c;以及相关的操作符进阶&#xff…

leetcode 1421 净现值查询(postgresql)

需求 表: NPV ---------------------- | Column Name | Type | ---------------------- | id | int | | year | int | | npv | int | ---------------------- (id, year) 是该表主键. 该表有每一笔存货的年份, id 和对应净现值的信息. 表: Queries ---------------------- …

Nginx -Web服务器/反向代理/负载均衡

文章目录 一、web服务1.1 nginx安装1.2 配置文件1.3 Nginx处理Web机制 二、反向代理三、负载均衡3.1 分类3.2 负载相关配置文件3.3 keepalive 提高吞吐量3.4 配置浏览器缓存 附、JMeter性能测试工具 以赛促学内容,大概率感觉会使用nginx做web服务,特对nginx做总结归纳. Nginx是…

AI in Finance 金融领域AI应用-基于DeepNLP AI App Store 真实用户评论打分和排名

AI在金融领域应用 AI in Finance 金融服务领域的AI应用和传统的金融智能应用不同。传统金融智能应用包括如风险评估 (Risk assessment), 风险管理&#xff08;Risk management), 欺诈检测 (Fraud Detection&#xff09;等等。 通用AI大模型和人工智能应用如ChatGPT&#xff0c…

PyTorch复现PointNet——模型训练+可视化测试显示

因为项目涉及到3D点云项目&#xff0c;故学习下PointNet这个用来处理点云的神经网络 论文的话&#xff0c;大致都看了下&#xff0c;网络结构有了一定的了解&#xff0c;本博文主要为了下载调试PointNet网络源码&#xff0c;训练和测试调通而已。 我是在Anaconda下创建一个新的…

香蕉派BPI-Wifi6迷你路由器公开发售

Banana Pi BPI-Wifi6 Mini 公开发售。 Banana Pi BPI-Wifi6 Mini 开源路由器采用Triductor TR6560 TR5220 wifi SOC设计&#xff0c;是一款迷你尺寸的wifi6路由器解决方案。内置高性能双核ARM Cortec A9处理器用于WIFI报文转发或智能业务处理&#xff0c;内置高性能LSW和硬件N…

最新浪子授权系统网站源码 全开源免授权版本

最新浪子授权系统网站源码 全开源免授权版本 此版本没有任何授权我已经去除授权&#xff0c;随意二开无任何加密。 更新日志 1.修复不能下载 2.修复不能更新 3.修复不能删除用户 4.修复不能删除授权 5.增加代理后台管理 6.重写授权读取文件 7.修复已经知道漏洞 源码下…