MobX
介绍
需求,组件0 改变了数据,其它组件也想获得改变后的数据,如图所示
这种多个组件之间要共享状态数据,useState 就不够用了,useContext 也不好用了
能够和 react 配合使用的状态管理库有
-
MobX
-
Redux
其中 Redux API 非常难以使用,这里选择了更加符合人类习惯的 MobX,它虽然采用了面向对象的语法,但也能和函数式的代码很好地结合
文档
-
MobX 中文文档
-
MobX 官方文档
安装
npm install mobx mobx-react-lite
在异步操作里为状态属性赋值,需要放在 runInAction 里,否则会有警告错误
使用 store,所有使用 store 的组件,为了感知状态数据的变化,需要用 observer 包装,对应着图中 reactions
-
mobx 目前版本是 "mobx": "^6.10.2"
-
mobx-react-lite 目前版本是 "mobx-react-lite": "^4.0.5"
-
名词
-
Actions 用来修改状态数据的方法
-
Observable state 状态数据,可观察
-
Derived values 派生值,也叫 Computed values 计算值,会根据状态数据的改变而改变,具有缓存功能
-
Reactions 状态数据发生变化后要执行的操作,如 react 函数组件被重新渲染
-
使用
首先,定义一个在函数之外存储状态数据的 store,它与 useState 不同:
-
useState 里的状态数据是存储在每个组件节点上,不同组件之间没法共享
-
而 MobX 的 store 就是一个普通 js 对象,只要保证多个组件都访问此对象即可
-
import axios from "axios"; import { Student } from "../model/Student"; import { makeAutoObservable, runInAction, makeObservable, observable, action, computed } from 'mobx' import R from "../model/R"; class StudentStore { //属性 对应状态数据(observable state),可观察 @observable student: Student = { id: 0, name: 'zhangsan' } //对应着action方法(用来修改状态数据的方法) //手动标识的时候使用 @action @action setName(name: string) { this.student.name = name } //对应着action方法(用来修改状态数据的方法) @action async fetch(id: number) { const resp = await axios.get<R<Student>>(`http://localhost:8080/api/students/${id}`) runInAction(() => { this.student = resp.data.data }) } //派生值(derived values)或者叫计算值(computed values)会根据状态数据的改变而改变,计算值具有一个特性, //它具有缓存功能,比如第一次输入的是宋远桥,会计算出是宋大侠,第二次以及之后,如果宋远桥不变,那 //么displayName不会再执行了,它第一次执行的时候会把结果缓存起来 @computed get displayName() { console.log('dispalyName 执行了') const first = this.student.name.charAt(0) if (this.student.sex === '男') { return first + '大侠' } else if (this.student.sex === '女') { return first + '女侠' } else { return '' } } //构造器 constructor() { //手动标识的时候使用 makeObservable(this) //自动使用的时候使用,如果不使用此代码,那么属性和方法就是普通属性和方法 //makeAutoObservable(this) } } export default new StudentStore()
其中 makeAutoObservable 会
-
将对象的属性 student 变成 Observable state,即状态数据
-
将对象的方法 fetch 变成 Action,即修改数据的方法
-
将 get 方法变成 Computed values
-
手动标识的时候需要在在tsconifg.json 中加入配置
-
{ "compilerOptions": { // ... "experimentalDecorators": true } }