Mobx和Mobx-react:集中式状态管理

news2024/11/15 8:15:08

一、Mobx

(1) Mobx是一个功能强大,上手非常容易的状态管理工具。
(2) Mobx背后的哲学很简单: 任何源自应用状态的东西都应该自动地获得。只获取与自己相关的数据,不获取无关数据(redux则相反)
(3) Mobx利用getter和setter来收集组件的数据依赖关系,从而在数据发生变化的时
候精确知道哪些组件需要重绘,在界面的规模变大的时候,往往会有很多细粒度更新,提升性能.
二、Mobx与redux

Mobx写法上更偏向于OOP(面向对象)。
对一份数据直接进行修改操作,不需要始终返回一个新的数据。
并非单一store,可以多store。
Redux默认以JavaScript原生对象形式存储数据,而Mobx使用可观察对象

三、mobx安装:npm install mobx@6

四、mobx使用

1.普通数据类型和复杂数据类型使用案例

不加装饰器的话只能处理同步,处理不了异步


import React, { Component } from 'react';
//observable:转换为可观察对象
//autorun:监听
import  { observable,autorun } from 'mobx';

//普通类型数据的监听
var observableNumber=observable.box(99);
var observableName=observable.box("66球");

//第一次加载时执行,之后每次更新都会执行
//autorun更新到才会执行
autorun(()=>{
    console.log(observableNumber.get());
})
autorun(()=>{
    console.log(observableName.get());
})

setTimeout(() => {
    observableNumber.set(100)
}, 2000);
setTimeout(() => {
    observableName.set("溜溜球")
}, 1000);


//对象
var obj=observable.map({
    name:"刘德华",
    age:18
});
autorun(()=>{
    console.log(obj.get('name'));
})
setTimeout(() => {
    obj.set('name','华仔')
}, 3000);
setTimeout(() => {
    obj.set('age',19)
}, 4000);


class App extends Component {
    render() {
        return (
            <div>
                App
            </div>
        );
    }
}

export default App;

 2.es7装饰器语法应用-可以处理异步

①.让vscode编辑器支持es7装饰器语法

点击文件-首选项-搜索experimentaPecorators-勾选

②.让react支持es7装饰器语法

安装:npm i @babel/core @babel/plugin-proposal-decorators @babel/preset-env

创建 .babelrc文件

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

创建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())

 安装依赖

npm i customize-cra react-app-rewired

修改package.json

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

注意:改完配置文件之后要重启服务器: npm start

3.案例

①.store.js

runInAction :解决异步问题


// observable:转换为可观察对象
// autorun:监听
//runInAction:处理异步
import {observable, configure, action,runInAction} from 'mobx';
import axios from 'axios';
// 严格模式, 必须写action,
// 如果是never,可以不写action,
// 最好设置always, 防止任意地方修改值, 降低不确定性。
configure({enforceActions: "always"})

class Store{
    @observable isTabbarShow=true;
    @observable list=[];
    @observable cityName="深圳";

    @action changeShow(){
        this.isTabbarShow = true
    }
    @action changeHide(){
        this.isTabbarShow = false
    }

    //异步
    @action getCinemaList(){
        axios({
            url:"https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=7406159",
            method:"get",
            headers:{
                'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.0.4","e":"16395416565231270166529","bc":"110100"}',
                
                'X-Host': 'mall.film-ticket.cinema.list'
      
            }
        }).then(res=>{
            // runInAction 解决异步问题
            runInAction(()=>{
                this.list=res.data.data.cinemas
            })
        })
    }
  
}
export default new Store();

②.isTabbarShow应用

app.js中显示isTabbarShow


import React, { Component } from 'react';
import Mrouter from "./router/indexRouter";
import Tabbar from "./component/Tabbar";
import "./App.css";
import {autorun} from "mobx";
import store from "./mobx/store";

export default class App extends Component {
  state={
    isShow:false
  }
  componentDidMount() {
    autorun(()=>{
      console.log(store.isTabbarShow);
      this.setState({
        isShow:store.isTabbarShow
      })
    })
  }
  
  render() {
    return (
      <div>
        <Mrouter>
        {this.state.isShow && <Tabbar></Tabbar>}
        </Mrouter>
      </div>
    )
  }
}

组件中调用方法changeShow和changeHide控制isTabbarShow

import React,{useEffect} from 'react';
import store from '../mobx/store';

export default function Detail(props) {
   useEffect(() => {
    console.log("create创建");
    store.changeHide()
    return () => {
      store.changeShow()
      console.log("cleanup销毁");
    };
   }, []);

  return (
    <div>Detail</div>
  )
}

③.应用

unsubscribe():自定义方法取消订阅,需要手动取消订阅


import React, { useState, useEffect } from "react";
import store from "../mobx/store";
import {autorun} from 'mobx';

export default function Cinemas(props) {
  const [cinemaList, setcinemaList] = useState([]);

  useEffect(() => {
    if(store.list.length === 0){
      store.getCinemaList()
    }
    var unsubscribe=autorun(()=>{
      console.log(store.list);
      setcinemaList(store.list)
  })
    return () => {
      //取消订阅
      unsubscribe()
    };
  }, []);
 

  return (
    <div>
      <div>
        {cinemaList.map((item) => (
          <dl key={item.cinemaId} style={{padding:"10px"}}>
            <dt>{item.name}</dt>
            <dd style={{fontSize:'12px',color:"gray"}}>{item.address}</dd>
          </dl>
        ))}
      </div>
      cinemaList
    </div>
  );
}

五、mobx-react

1.安装:npm install mobx-react@7

(1)react 组件里使用 @observer
observer 函数/装饰器可以用来将 React 组件转变成响应式组件。
(2) 可观察的局部组件状态
@observable 装饰器在React组件上引入可观察属性。而不需要通过 React 的冗长和强制性的 setState 机制来管理。

(3)Provider 组件
它使用了 React 的上下文(context)机制,可以用来向下传递 stores。 要连接到这些 stores,需要传递一个 stores名称的列表给 inject,这使得 stores 可以作为组件的 props 使用。this.props

 2.案例

①.store.js


// observable:转换为可观察对象
// autorun:监听
//runInAction:处理异步
import {observable, configure, action,runInAction} from 'mobx';
import axios from 'axios';
// 严格模式, 必须写action,
// 如果是never,可以不写action,
// 最好设置always, 防止任意地方修改值, 降低不确定性。
configure({enforceActions: "always"})

class Store{
    @observable isTabbarShow=true;
    @observable list=[];
    @observable cityName="深圳";

    @action changeShow(){
        this.isTabbarShow = true
    }
    @action changeHide(){
        this.isTabbarShow = false
    }

    //异步
    @action getCinemaList(){
        axios({
            url:"https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=7406159",
            method:"get",
            headers:{
                'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.0.4","e":"16395416565231270166529","bc":"110100"}',
                
                'X-Host': 'mall.film-ticket.cinema.list'
      
            }
        }).then(res=>{
            // runInAction 解决异步问题
            runInAction(()=>{
                this.list=res.data.data.cinemas
            })
        })
    }
  
}
export default new Store();

②.主入口文件index.js

import App from "./10-mobx/04-router/App";
import {Provider} from "mobx-react";
import store from "./10-mobx/04-router/mobx/store";

const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render( 
  <div className="box">
    <Provider store={store}>
      <App/>
    </Provider>
    </div>
   );

 ③.app.js


import React, { Component } from 'react';
import Mrouter from "./router/indexRouter";
import Tabbar from "./component/Tabbar";
import "./App.css";
import {observer,inject} from "mobx-react";

//mobx-react利用高阶组件构建一个父组件
@inject("store")//注入store
@observer
export default class App extends Component {
  componentDidMount() {
    console.log(this.props.store);//所有store值
  }
  
  render() {
    return (
      <div>
        <Mrouter>
        {this.props.store.isTabbarShow && <Tabbar></Tabbar>}
        </Mrouter>
      </div>
    )
  }
}

④.子页面 .此组件是函数式组件,不用装饰器的写法,用标签的写法<Observer></Observer>,无状态,无需设置取消订阅,会自动取消订阅


import React, { useState, useEffect } from "react";
import store from "../mobx/store";
import {autorun} from 'mobx';
import {Observer} from 'mobx-react';

export default function Cinemas(props) {

  useEffect(() => {
    if(store.list.length === 0){
      store.getCinemaList()
    }
    return () => {
      //取消订阅
    };
  }, []);
 

  return (
    <div>
      <Observer>
      {
        ()=>{
          return <div>
          {store.list.map((item) => (
            <dl key={item.cinemaId} style={{padding:"10px"}}>
              <dt>{item.name}</dt>
              <dd style={{fontSize:'12px',color:"gray"}}>{item.address}</dd>
            </dl>
          ))}
        </div>
        }
      }
      </Observer>
      cinemaList
    </div>
  );
}

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

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

相关文章

科技兴警,优云「公安一体化安全运维解决方案」亮相2023警博会

日前&#xff0c;第十一届中国国际警用装备博览会&#xff08;警博会&#xff09;在北京首钢会展中心成功举办&#xff0c;600余家企业参展&#xff0c;集中展示国内外前沿警用装备及尖端技术&#xff0c;大力推进警用装备现代化。 国内领先的平台级数字化运维软件服务商广通优…

TDengine集群搭建

我这里用三台服务器搭建集群 1、如果搭建集群的物理节点上之前安装过TDengine先卸载清空&#xff0c;直接执行以下4条命令 rmtaos rm -rf /var/lib/taos rm -rf /var/log/taos rm -rf /etc/taos2、确保集群中所有主机开放端口 6030-6043/tcp&#xff0c;6060/tcp&#xff0c;…

flink的几种source来源

简单的总结了flink的几种source来源&#xff0c;可以参考下 package com.atguigu.apitestimport java.util.Propertiesimport org.apache.flink.api.common.serialization.SimpleStringSchema import org.apache.flink.streaming.api.functions.source.SourceFunction import …

涨点技巧:注意力机制---Yolov8引入Resnet_CBAM,CBAM升级版

1.计算机视觉中的注意力机制 一般来说,注意力机制通常被分为以下基本四大类: 通道注意力 Channel Attention 空间注意力机制 Spatial Attention 时间注意力机制 Temporal Attention 分支注意力机制 Branch Attention 1.1.CBAM:通道注意力和空间注意力的集成者 轻量级…

版本控制系统有哪些推荐? - 易智编译EaseEditing

以下是几个常用的版本控制系统&#xff08;Version Control System&#xff09;推荐&#xff0c;并对它们进行简单介绍&#xff1a; Git&#xff1a; Git是目前最流行的分布式版本控制系统。它具有高效、灵活和强大的功能&#xff0c;支持快速的代码提交、分支管理、合并操作…

高频面试八股文原理篇(五)索引相关

目录 索引的优缺点 MySQL索引类型 索引原理 常见索引类型 MySQL数据库要⽤B树存储索引⽽不⽤红⿊树、B树、 Hash的原因 怎么验证 MySQL 的索引是否满足需求 聚簇索引和非聚簇索引 索引的优缺点 索引的优点 可以大大加快数据的检索速度&#xff0c;这也是创建索引的最主…

蚂蚁Ant Design组件库的免费在线资源

Ant Design&#xff08;蚂蚁组件&#xff09;是蚂蚁集团体验技术部经过大量项目实践和总结&#xff0c;逐步打磨出的一个设计系统&#xff0c;内含带有 React 的 UI 库。它是为企业级产品设计而创建的。Ant Design 提供了高质量的交互界面设计组件和演示。作为 UI 设计师&#…

Spring:Spring框架结构 ②

一、结构体现的价值 1、可读性强。 2、可维护性。 3、优秀的框架均具有分而治之的思想。清晰的设计、合理的归类、模块化是走向优秀框架的基础性武器。 二、Spring框架的模块划分 1、整体轮廓 Spring框架包含的功能大约由20个小模块组成。这些模块按组可分为核心容器(Core Co…

独立、相关、正交

文章目录 【1. 独立】【2. 相关】【3.正交】【4. 相互关系】相关和独立相关和正交独立和正交独立、不相关和正交小结 【5. 参考文献】 【1. 独立】 独立&#xff1a;对于两个随机变量 y 1 y_1 y1​ 和 y 2 y_2 y2​&#xff0c;若 y 1 y_1 y1​ 的有关信息不给出 y 2 y_2 …

基于AT89C52单片机的无线温度监测设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87848530?spm1001.2014.3001.5503 源码获取 主要内容&#xff1a; 设计一个温度监测器&#xff0c;温度异常时警报器能够响起&#xff0c;设定初始温度&#xff0…

0基础学习VR全景平台篇第33章:场景功能-嵌入标尺

功能位置示意 一、本功能将用在哪里&#xff1f; 嵌入功能可对VR全景作品嵌入【图片】【视频】【文字】【标尺】四种不同类型内容&#xff1b; 本次主要带来标尺类型的介绍&#xff0c;可对VR全景作品中&#xff0c;位置信息较多的场景进行标注&#xff0c;在单场景中植入更多…

R-Meta分析与【文献计量分析、贝叶斯、机器学习等】多技术融合实践

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

linux守护进程简单创建

1.什么是守护进程&#xff1f; 守护进程(daemon)是一类在后台运行的特殊进程&#xff0c;用于执行特定的系统任务。很多守护进程在系统引 导的时候启动&#xff0c;并且一直运行直到系统关闭。另一些只在需要的时候才启动&#xff0c;完成任务后就自动结束。 用户使守护进程独立…

平行云X火山引擎:探索XR观展的极致体验

5月20日&#xff0c;素有艺术界“奥林匹克”之称的第18届威尼斯国际建筑双年展&#xff08;以下简称“威尼斯双年展”&#xff09;中国国家馆展览正式开幕。 威尼斯双年展为当今世界规模最大、最具影响力的国际艺术盛事之一&#xff0c;中国文化和旅游部自2005年起主办中国国家…

六一儿童节海外网红营销指南:出海品牌的增长秘诀

六一儿童节作为全球范围内备受关注的节日之一&#xff0c;为孩子们提供了欢乐和庆祝的机会。对于出海品牌来说&#xff0c;利用六一儿童节进行海外网红营销不仅可以吸引年轻消费者的关注&#xff0c;还能够增加品牌的知名度和影响力。根据行业研究机构Statista的数据&#xff0…

第十三章行为型模式—模板模式

文章目录 模板模式解决的问题结构实例存在的问题适用场景 JDK源码 - InputStream 行为型模式用于描述程序在运行时复杂的流程控制&#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务&#xff0c;它涉及算法与对象间职责的分配。行为型模式分为…

hive如何实现oracle的connect by prior函数

Hive中如何实现层级查询 类似oracle中 connect by prior 实现的效果&#xff1f; - 知乎 大佬写的很详细&#xff0c;有兴趣自己看&#xff0c;但是存在一个问题 create table test.emp ( empno string, ename string, job string, mgr strin…

如何使用MapStruct优雅的告别get,set

我们开发过程中会遇到很多bean拷贝的过程&#xff0c;最简单粗暴得方法就是set/get方法&#xff0c;当然这也是最臃肿的方法&#xff0c;代码显得过于冗长和笨重&#xff0c;其次还有框架BeanUtils在使用反射的时候都会影响到性能。虽然我们可以进行反射信息的缓存来提高性能。…

网络安全实用篇—iptables防火墙学习总结

iptables防火墙学习总结 目录 iptables简介&#xff1a; iptables题目练习&#xff1a; 题目包含&#xff08;市赛、省赛、国赛&#xff09;覆盖所有比赛面&#xff01; iptables简介&#xff1a; Iptables是Linux系统中的一个防火墙工具&#xff0c;它可以对进出本机的…

用Photoshop软件制作法线图以及查看效果细节

这里是在windows系统下用PS2020做演示。 第一步、在Photoshop软件中打开一张图(最好是正方形&#xff0c;边长是2的n次方大小的像素&#xff0c;例如宽和高都是512像素)&#xff0c;如下图所示&#xff1a; 第二步、在菜单栏选择滤镜然后再选择3D接着再选择生成法线图&#xf…