Mobx 是一个和 React 良好配合的集中状态管理工具,mobx 和 react 的关系,相当于 vuex 和 vue
同类工具还有 redux、dva、recoil 等
环境配置
Mobx 是一个独立响应式的库,可以独立于任何 UI 框架存在,但是人们通常把它和 React 绑定起来使用,用 Mobx 来做响应式数据建模,React 作为 UI 视图框架来渲染内容
环境配置需要三个部分
- 一个通过 create-react-app 创建好的项目环境
- mobx 本身
- 一个链接 mobx 和 react 的中间部件
- 使用 create-react-app 初始化项目
npx create-react-app mobx-react-app
- 安装 mobx 和 mobx-react-lite
yarn add mobx mobx-react-lite
npm i mobx mobx-react-lite
第一个 store
初始化 mobx
实现步骤
- 定义数据状态(state)
- 数据相应式处理
- 定义 action 函数(修改数据)
- 实例化并导出实例
import { makeAutoObservable } from "mobx";
// 编写一个mobx store小案例
class CounterStore {
// 1. 定义数据
count = 0;
constructor() {
// 2.把数据弄成响应式
makeAutoObservable(this);
}
// 3.定义action函数(修改数据)
addCount = () => {
this.count++;
};
}
// 4.实例化 然后导出给react使用
const counterStore = new CounterStore();
export { counterStore };
连接 react
实现步骤
- 导入 store 实例
- 使用 store 中的数据
- 修改 store 中的数据
- 让组件视图响应数据变化
import React from "react";
// 导入
import { counterStore } from "./store/counter";
// 导入中间件连接mobx-react完成响应式变化
import { observer } from "mobx-react-lite";
function App() {
return (
<div>
{/* 渲染store中的counter */}
<h1>{counterStore.count}</h1>
{/* 点击事件触发action函数修改count值 */}
<button onClick={counterStore.addCount}>累加</button>
</div>
);
}
// 包裹App
export default observer(App);
mobx-computed 计算属性
基于一个原始的数据,经过一定的计算得到一个新数据,且能在原始数据发生变化的时候完成重新计算.
computed-如何实现
- 声明一个存在的数据
- 定义 get 计算属性
- 在 makeAutoObservable 方法中标记
import { makeAutoObservable } from "mobx";
class CounterStore {
// 定义一个原始数据list
list = [1, 2, 3, 4, 5, 6];
constructor() {
makeAutoObservable(this);
}
// 定义计算属性
get filterList() {
return this.list.filter((item) => {
return item > 2;
});
}
//修改list
addList = () => {
this.list.push(7, 8, 9);
};
}
const counterStore = new CounterStore();
export { counterStore };
在 react 中使用
import React from "react";
import { counterStore } from "./store/counter";
import { observer } from "mobx-react-lite";
function App() {
return (
<div>
{/* 使用计算属性 */}
{counterStore.filterList}
<button onClick={counterStore.addList}>修改list</button>
</div>
);
}
// 包裹App
export default observer(App);
Mobx 模块化
一个项目中有很多业务模块,我们不能把所有代码都写到一起,这样很难维护,为了提供可维护性,需要引入模块化
比如上面的例子,我们要拆分 count 和 list 模块
- 拆分 count 和 list 模块,每个模块定义自己独立的 state/actions
- 在 store/index.js 下导入拆分后的模块,进行模块组合
- 使用 React 的 useContext 机制导出 useStore 方法,供业务组件统一使用.
liststore.store.js
import { makeAutoObservable } from "mobx";
class ListStore {
list = ["Vue", "React"];
constructor() {
makeAutoObservable(this);
}
addList = () => {
this.list.push("Angular");
};
}
export { ListStore };
counter.store.js
import { makeAutoObservable } from "mobx";
// 编写一个mobx store小案例
class CounterStore {
// 1. 定义数据
count = 0;
// 定义一个原始数据list
list = [1, 2, 3, 4, 5, 6];
constructor() {
// 2.把数据弄成响应式
makeAutoObservable(this);
}
// 定义计算属性
get filterList() {
return this.list.filter((item) => {
return item > 2;
});
}
//修改list
addList = () => {
this.list.push(7, 8, 9);
};
// 3.定义action函数(修改数据)
addCount = () => {
this.count++;
};
}
export { CounterStore };
index.js
// 组合子模块
// 封装统一导出的供业务使用的方法
import React from "react";
import { ListStore } from "./list.store";
import { CounterStore } from "./counter.store";
// 1. 声明一个rootStore
class RootStore {
constructor() {
// 对子模块进行实例化操作
// 将来实例化根store的时候
// 根store有两个属性 分别是counterStore和listStore
// 各自对应的值,就是我们导入的子模块实例对象
this.counterStore = new CounterStore();
this.listStore = new ListStore();
}
}
// 实例化操作
const rootStore = new RootStore();
// 使用react conntext机制 完成统一方法封装
// Provider value={传递的数据}
// 查找的机制: useContext 优先从Provider value找 如果找不到 就会找createContext方法传递过来的默认参数
const context = React.createContext(rootStore);
// 这个方法作用:通过useContext拿到rootStore实例对象 然后返回
// 只要在业务组件中 调用useStore()->rootStore
const useStore = () => React.useContext(context);
export { useStore };
App.jsx
import React from "react";
import { useStore } from "./store/index";
import { observer } from "mobx-react-lite";
function App() {
const rootStore = useStore();
console.log(rootStore);
return (
<div>
{rootStore.counterStore.count}
<button onClick={rootStore.counterStore.addCount}>累加</button>
</div>
);
}
export default observer(App);
也可以用解构赋值
App.jsx
import React from "react";
import { useStore } from "./store/index";
import { observer } from "mobx-react-lite";
function App() {
const { counterStore } = useStore();
console.log(counterStore);
return (
<div>
{counterStore.count}
<button onClick={counterStore.addCount}>累加</button>
</div>
);
}
export default observer(App);
Q.E.D.