一、介绍
MobX 是一个身经百战的库,它通过运用透明的函数式响应编程(Transparent Functional Reactive Programming,TFRP)使状态管理变得简单和可扩展。
简单直接
编写无模板的极简代码来精准描述出你的意图。要更新一个记录字段?使用熟悉的 JavaScript 赋值就行。要在异步进程中更新数据?不需要特殊的工具,响应性系统会侦测到你所有的变更并把它们传送到其用武之地。
轻松实现最优渲染
所有对数据的变更和使用都会在运行时被追踪到,并构成一个截取所有状态和输出之间关系的依赖树。这样保证了那些依赖于状态的计算只有在真正需要时才会运行,就像 React 组件一样。无需使用记忆化或选择器之类容易出错的次优技巧来对组件进行手动优化。
架构自由
MobX 不会用它自己的规则来限制你,它可以让你在任意 UI 框架之外管理你的应用状态。这样会使你的代码低耦合、可移植和最重要的——容易测试。
二、环境搭建
- 使用
create-react-app
脚手架搭建的 react项目
$ npx create-react-app mobx-react-app
- 安装
Mobx
、中间件mobx-react-lite
(仅支持函数组件)
$ npm i mobx mobx-react-lite
- mobx-react-appx工程 src 目录下新建 store 文件夹,后续操作在该文件夹内操作
二、使用
1.初始化mobx
- 定义数据状态 state
- 数据响应式处理
- 定义 action 函数(修改数据)
- 实例化并导出实例
// src/store/count.js mobx store实例
import { makeAutoObservable } from "mobx";
class CountStore {
// 1. 定义数据状态
count = 0;
constructor () {
// 2. 数据响应式处理
makeAutoObservable(this);
}
addCount = () => {
// 3. 定义 action 函数
this.count ++;
}
}
// 实例化
const countStore = new CountStore();
export {countStore};
2. 连接react
- 导入 store实例
- 使用 store 数据
- 修改store数据
- 使用中间件 方法 响应化数据
// App.js
import React from "react";
// 1.导入 store 实例
import {countStore} from './store/count';
// 4. 导入 中间件的 方法 响应化视图
import {observer} from 'mobx-react-lite';
function App() {
return (
<div>
app
{/**2.使用store数据 */}
{countStore.count}
{/**3.通过store实例方法 修改数据 */}
<button onClick={countStore.addCount}>add</button>
</div>
)
}
// observer 包裹App,实现视图响应式
export default observer(App);
3.computed计算属性
- 声明一个数据
- 定义 get 计算属性
- 在 makeAutoObservable 方法中标记
// src/store/count
import { makeAutoObservable, computed } from "mobx";
class CountStore {
list = [1,2,3,4]
constructor () {
// 数据响应式处理
makeAutoObservable(this, {
filterlist:computed // 计算属性标记,为何这里不标记,也可以?????
});
}
// 定义 get计算属性
get filterlist() {
return this.list.filter(n => n > 2);
}
addList = () => {
this.list.push(6,7,8)
}
}
// 实例化
const countStore = new CountStore();
export {countStore};
问题解答:
- 为什么不设置
filterlist:computed
属性,也能 响应式更新?
因为makeAutoObservable
会将所有的 getters 被自动声明为computed
,相同功能的还有observable
、extendObservable
// App.js
import React from "react";
// 1.导入 store 实例
import {countStore} from './store/count';
// 4. 导入 中间件的 方法 响应化视图
import {observer} from 'mobx-react-lite';
function App() {
return (
<div>
{countStore.list.join('-')}
<button onClick={countStore.addList}>push</button>
</div>
)
}
// observer 包裹App,实现视图响应式
export default observer(App);
三、Mobx模块化
操作步骤
- 拆分count、list模块,每个模块定义自己的 state/action
- 在 store/index.js 中导入拆分后的模块,进行模块组合
- 使用 React 的
useContext
机制导出 useStore 方法,供业务组件统一使用
// store/list.Store.js
// 子模块1 listStore
import { makeAutoObservable } from "mobx";
class ListStore {
list = ['李白','杜甫'];
constructor () {
makeAutoObservable(this)
}
addList = () => {
this.list.push('白居易')
}
}
export {ListStore}
// store/count.Store.js
// 子模块2: countStore
import { makeAutoObservable, computed } from "mobx";
class CountStore {
// 1. 定义数据状态
count = 0;
list = [1,2,3,4]
constructor () {
// 2. 数据响应式处理
makeAutoObservable(this, {
// filterlist:computed // 计算属性标记
});
}
addCount = () => {
// 3. 定义 action 函数
this.count ++;
}
// 定义 get计算属性
get filterlist() {
return this.list.filter(n => n > 2);
}
addList = () => {
this.list.push(6,7,8)
}
}
export {CountStore};
// store/index.js
// 组合子模块
import { createContext, useContext } from 'react';
import {ListStore} from './list.Store';
import { CountStore } from './count.Store';
class RootStore {
constructor () {
// 实例化子模块
// 后续 根store 有两个属性,分别是 listStore 和 countStore
this.listStore = new ListStore();
this.countStore = new CountStore();
}
}
// 实例化操作
const rootStore = new RootStore();
// 通过 createContext机制,完成统一封装
// 查找机制:useContext 优先从 Provider value找,如果找不到,就会找 createContext 传递过来的默认参数
const context = createContext(rootStore);
const useStore = () => useContext(context);
export {useStore}
// App.js
import React from "react";
import {observer} from 'mobx-react-lite';
import { useStore } from "./store";
function App() {
const {countStore} = useStore();
return (
<div>
{countStore.count}
<button onClick={countStore.addCount}>add</button>
</div>
)
}
// observer 包裹App,实现视图响应式
export default observer(App);
```