React--》状态管理工具—Mobx的讲解与使用

Posted 亦世凡华、

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React--》状态管理工具—Mobx的讲解与使用相关的知识,希望对你有一定的参考价值。

目录

Mobx的讲解与使用

Mobx环境配置

Mobx的基本使用

Mobx计算属性的使用

Mobx监听属性的使用

Mobx处理异步的使用

Mobx的模块化


Mobx的讲解与使用

Mobx是一个可以和React良好配合的集中状态管理工具,mobx和react的关系相当于vuex和vue之间的关系,同类工具还有:redux、dva、recoil。

mobx优势:编写无模板的极简代码来精准描述你的意图;依赖自动追踪最小渲染优化轻松实现最优渲染;可移植和测试轻松实现架构自由;学习成本小且面向对象编程,对TS友好。

mobx的核心思想:任何源自应用状态的东西都应该自动的获得。

Mobx与redux的区别:Mobx写法上更偏向于OOP(面向对象编程),对一份数据直接进行修改操作,不需要始终返回一个新的数据;并非单一store,可以是对store; redux默认以javascript原生对象形式存储数据,而Mobx使用可观察对象。详细比较如下:

reduxmobx
有严格的工作流程,需要写大量的模板代码无模板代码,非常简洁
需要保证数据不可变数据是响应式的,可以直接修改数据(proxy)
redux需要中间件处理异步mobx可以直接处理异步
redux约束强,更适合大型多人协作开发mobx适合简单,规模不大的应用

Mobx版本说明:经过时间的积淀,mobx也迎来了许多版本的迭代,其中具体的版本说明如下:

Mobx4可以运行在任何支持ES5语法的浏览器(Object.defineProperty)

Mobx5版本运行在任何支持ES6语法的浏览器(Proxy)

Mobx4和Mobx5具有相同的api,都需要使用装饰器语法

Mobx6是目前最新版本,为了与标准的JavaScript的最大兼容性,默认情况下放弃了装饰器语法,因为装饰器语法仅仅是给提案,举例ES标准化还需要很久。

还是那句老生常谈的话:想了解前沿技术还是多多看看官方手册:mobx官方文档

Mobx环境配置

Mobx是一个独立的响应式的库,可以独立于任何UI框架而存在,但是通过人们把它和React来绑定使用,用Mobx来做响应式数据建模,React作为UI视图架构渲染内容。配置Mobx如下:

通过类似create-react-app创建好的react项目环境,使用create-react-app初始化react项目,如果要详细了解react框架的搭建,推荐看一下这篇文章:React脚手架的搭建与使用

npx create-react-app 项目名称

安装 mobx 和 mobx-react或mobx-react-lite,这里简单提一下:mobx-react和mobx-react-lite都是连接react和mobx的中间件,两种的区别是mobx-react支持类和函数组件,体积相对而言较大;而mobx-react-lite只支持函数组件,体积较小,自己可以根据具体情况进行使用下载:

npm install mobx mobx-react-lite

Mobx的基本使用

安装好mobx相关的第三方包之后,就可以使用mobx进行状态管理了,如下,在src目录下新建一个store文件夹,在store文件夹下新建一个counter.jsx文件,用来管理count状态,如下:

import  action, makeObservable, observable  from "mobx";

class Counter 
  constructor()
    // 参数1:target 把谁变成响应式(可观察);参数2:指定哪些属性或方法变成可观察
    makeObservable(this, // 设置观察模式
      count:observable, // 设置管理状态的数据
      increment:action.bound,  // 可以设置bound属性修改this指向
      decrement:action,
      reset:action
    )
  
  // 当前的初始化状态数据
  count = 0
  
  // 操作状态的方法
  increment()
    this.count++
  
  decrement()
    this.count--
  
  reset()
    this.count = 0
  

// eslint-disable-next-line import/no-anonymous-default-export
export default new Counter()

在想使用count数据的相关组件中进行引入并使用即可,过程如下:

import React from 'react'
import  observer  from 'mobx-react-lite'
import counter from './store/counter'

function App() 
  return (
    <div>
      <h3>计数器案例</h3>
      <div>点击次数:counter.count</div>
      <button onClick=()=>counter.increment()>加1</button>
      <button onClick=()=>counter.decrement()>减1</button>
      <button onClick=()=>counter.reset()>重置</button>
    </div>
  )


// 使用ovserver高阶组件函数包裹需要使用store的组件
export default observer(App)

默认情况下class中的方法不会绑定this,this指向取决于如何调用,当然如果你想调用函数时不想通过箭头函数来调用函数,在使用makeAutoObservable时可以通过bound属性来修改指向问题:

makeAutoObservable的使用:makeAutoObservable就像加强版的makeObservable,默认情况下它将推断所有的属性,推断的规则为:所有的属性都成为observable,所有的方法都成为action,所有的计算属性都成为computed (计算属性接下来会讲到)。具体的使用如下:

import  makeAutoObservable  from "mobx";

class Counter 
  constructor()
    // 参数1:target让对象变成可观察
    // 参数2:排除属性和方法
    // 参数3:指定自动绑定this
    makeAutoObservable(this,,autoBind:true)
  
  // 当前的初始化状态数据
  count = 0
  // 操作状态的方法
  increment()
    this.count++
  
  decrement()
    this.count--
  
  reset()
    this.count = 0
  

// eslint-disable-next-line import/no-anonymous-default-export
export default new Counter()

Mobx计算属性的使用

computed可以用来从其它可观察对象中派生信息,计算值采用惰性求值,会缓存其输出,并且只有当其依赖的可观察对象被改变时才会重新计算。

注意:计算属性是一个方法,且方法前面必须使用get进行修饰,计算属性还需要通过makeAutoObservable方法指定,如下:

Mobx监听属性的使用

Mobx监听属性主要有以下两种方式,现在分别对两种监听方式的使用进行讲解,如下:

autoRun的使用

autoRun函数接受一个函数作为参数,每当该函数所观察的值发生变化时,它都应该运行,当自己创建 autoRun 时,它也会运行一次,Mobx会自动收集并订阅所有的可观察属性,一旦有改变发生,autorun将会再次执行。

import  autorun, makeAutoObservable  from "mobx";
class Counter 
  constructor()
    makeAutoObservable(this,,autoBind:true)
  
  count = 0
  increment()
    this.count++
  
  decrement()
    this.count--
  
  reset()
    this.count = 0
  

const counter = new Counter()
// 监听数据的变化
autorun(()=>
  console.log('counter.count',counter.count);
)
export default counter

reaction的使用

reaction类似于autorun,但可以更加精细地控制要跟踪的可观察对象,与autorun不同,reaction在初始化时不会自动运行。

import  makeAutoObservable, reaction  from "mobx";
class Counter 
  constructor()
    makeAutoObservable(this,,autoBind:true)
  
  count = 0
  increment()
    this.count++
  
  decrement()
    this.count--
  
  reset()
    this.count = 0
  

const counter = new Counter()
// 监听数据的变化
// reaction接收两个参数,参数1:data函数,其返回值会作为第二个函数的输入;参数2:回调函数
reaction(()=> counter.count,(value,oldvalue)=>
  console.log('count数据发生变化了',value,oldvalue);
)

export default counter

Mobx处理异步的使用

异步进程在Mobx中不需要任何特殊处理,因为不论是何时引起的所有 reactions 都将会自动更新,因为可观察对象是可变的,因此在action执行过程中保持对它们的引用一般是安全的,如果可观察对象的修改不是在action函数中,控制台会报警告(可以关闭,但是不推荐)。什么意思呢?如下:

我们在进行异步加一之后,打开浏览器的控制台,看看能得出什么结果,如下:

当然,控制台虽然爆出警告,但是不影响实际的效果的产生的,如果想消除警告,可以设置严格模式,如下:

这种虽然是能消除警告,但是并不符合规范,如果想符合规范的话,建议采用这种方式:

runlnAction的使用

Mobx处理异步的方式除了使用上面的方式外,还可以使用runlnAction进行异步处理,通过runlnAction可以保证所有异步更新可观察对象的步骤都应该标识为action,使用方式如下:

Mobx的模块化

在大型项目中,是不能将所有状态和方法都放到一个store中的,我们可以根据业务模块定义多个store,然后通过一个根store统一管理所有的store。一般我们会将在store文件夹下的index文件设置为根store,如下:

// 封装统一导出的store
import  createContext, useContext  from 'react';
// 两个store文件
import counter from './counter'
import list from "./list";

// 声明一个 RootStore
class RootStore 
  counter = counter
  list = list

const store = new RootStore()
// 创建一个上下文对象,用于跨级组件通讯
// 如果createContext提供了默认值,不需要Provider
const Context = createContext(store)
// 自定义hook
export default function useStore()
  return useContext(Context)

总结:Mobx5版本及之前版本对装饰器的语法,这里就不再讲解了,想要了解的朋友可以参考官方文档或者自行百度。

Mobx6React + Typescript 实践

Mobx6 + React + Typescript 实践

MobX 是一个React状态管理方案,它通过运用透明的函数式响应编程(Transparent Functional Reactive Programming,TFRP)使状态管理变得简单和可扩展。

使用 create-react-app 来快速创建 react 与 typescript 的环境。

需要安装依赖如下:

  1. mobx
  2. mobx-react 或 mobx-react-lite
pnpm install mobx mobx-react-lite

第一步,创建 store 目录。

src 目录下新建 store 文件夹,并创建 globalStore.ts 文件。

globalStore.ts

import makeAutoObservable, observable, action, runInAction from 'mobx'

// 定义用户信息数据store接口
export interface IData 
  name: string	// 昵称
  age: number // 年龄
  info: string	// 自我介绍
  editName: (str: string) => void;


class GlogalStore 
  name = '嘻嘻'
  age = 18
  info = '请多指教'
  
  constructor() 
  	// 方式一: 自动转化 target 对象的属性和方法
    makeAutoObservable(this)

	// 方式二: 手动注解
    makeObservable(this, 
      name: observable,
      age: observable,
      info: observable,
      editName: action,
    )
  

  editName(name: string) 
    runInAction(() => 
      this.name = name
    )
  


export default new GlogalStore()

第二步,创建 index 页面。

src 目录下新建 pages/Index/index.tsx 文件。

index.tsx

import observer from 'mobx-react-lite'
import globalStore from 'src/store/globalStore'

const Index = (props: any) => 
  return (
    <>
		<div>
			昵称:<span>globalStore.name</span>
			年龄:<span>globalStore.age</span>
			自我介绍:<span>globalStore.info</span>
			修改:<input type="text" @blur=(e) => globalStore.setName(e.target.value) />
		</div>
    </>
  )

export default observer(Index)

以上是关于React--》状态管理工具—Mobx的讲解与使用的主要内容,如果未能解决你的问题,请参考以下文章

React中的状态管理---Mobx

React中的状态管理---Mobx

React项目中使用Mobx状态管理

react状态管理器之mobx

Mobx6React + Typescript 实践

Mobx6React + Typescript 实践