Mobx 状态管理

可以少去理解一些不必要的概念,而多去思考为什么会有这样的东西,它解决了什么问题,或者它的运行机制是什么?

1. mobx 介绍

https://cn.mobx.js.org/

1)mobx 是一个功能强大,上手非常容易的状态管理工具。

2)mobx 背后的哲学很简单:任何源自应用状态的东西都应该自动获取。

3)mobx 利用 getter 和 setter 来收集组件的数据依赖关系,从而在数据发生变化的时候精确知道哪些组件需要重绘,在界面规模变大的时候,往往会有很多细粒度更新。

2. mobx 与 redux 的区别

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

优点:

  • 学习成本小。
  • 面向对象编程,而且对 TS 友好。

缺点:

  • 过于自由:mobx 提供的约定及模版代码很少,代码编写很自由,如果不做一些约定,比较容易导致团队代码风格不统一。
  • 相关的中间件很少,逻辑层业务整合是问题。

3. mobx 的使用

对普通类型数据的监听。对复杂类型(对象、数组等)数据的监听。

3.1 observable 和 autorun

observable 是把一个普通类型的数据,或者对象、数组复杂的数据转换为可观察的对象或数组。然后等你每次改这个值的时候,autorun 中监听函数就会被触发,所以 autorun 可以认为是一个监听者一样自动执行函数。

// 对普通函数的监听
import { observable, autorun } from 'mobx'

var observableNumber = observable.box(10)
// 第一次执行,之后每次改变也会执行
autorun(()=>{
  console.log(observableNumber.get())
})

setTimeout(()=>{
  observableNumber.set(20)
},1000)

// 对复杂类型(对象、数组等)数据的监听
const map = observable.map({key: 'value'})
const map = observable({key: 'value'})
const list = observable([1,2,3])

应用示例:

// store.js
import { observable } from 'mobx'
const store = observable({
  isTableShow: true,
  list:[]
  cityName:"hz"
})

// 修改
store.isTableShow = true

// 监听获取
store.isTableShow

3.2 configure 严格模式

严格模式(强制 action)下不允许在非 Actions 以外的地方修改可观察对象的值。进行约束代码,集中在 store 中管理,特别在团队合作开发的时候。

// store.js
import { observable, configure } from 'mobx'

configure({
  enforeActions:'always' // never 非严格模式,always 严格模式
})

const store = observable({
  isTableShow: true,
  list:[]
  cityName:"hz"
  changeShow() {
  	this.isTableShow = true
	}
	changeHide() {
  	this.isTableShow = false
	}
},{
  changeShow:action,
  changeHide:action  // 标记两个方法是 action,专门修改可观察的 value
})

// 修改 - 报错
//store.isTableShow = true
store.changeHide()

// 监听获取
store.isTableShow

3.3 Mobx 新语法写法之装饰器

ES7 中提供装饰器语法 @ 符号。把一个普通的函数传递给装饰器函数,返回一个更强大的函数。

为了支持装饰器语法需要进行以下相关配置,包括编译器支持配置和脚手架(工程)支持启用装饰器语法配置。

import (observable, action, configure, runInAction} from 'mobx';
configure({enforceActions: 'always'})
//严格模式,必须写action,如里是fever,可以不写action。最好设置always,防止任意地方修改值,降低不确定性。
class Store {
	@observable number = 0;
	@observable name = "kerwin";
	@action add = 0 => {
		this. number++;
	}//action只能影响正在运行的函数,而无法影响当前函数调用的异步操作
	@action load = async()=>{
		const data = await getData;
		runInAction(() => {
			this.name = data.name;
		});
}// runInAction 解决异步问題
const newstore = new Store();
newstore.add();

1)编译器配置 VSCode

对不属于任何工程的 JavaScript 文件启用或禁用 experimentalDecorators 设置。

2)脚手架(工程)支持启用装饰器语法

安装相关文件

npm i @babel/core @babel/plugin-proposal-decorator$ @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 ))

安装依赖,修改 package.json 中脚手架启动方式

npm i customize-cra react-app-rewired
"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  "eject": "react-app-rewired eject"
},

3.4 Mobx 异步处理 runInAction

store 中在 action 里处理异步请求,异步请求结果回来后直接修改可观察对象中的数据,会报运行时错误,提示严格模式下不允许在 action 外部修改 ??? 异步函数的问题,异步结果修改会认为是在不知名的函数中修改了数据,必须引入 runInAction。

runInAction(()=>{
	// 在这里修改数据
})

3.5 Mobx 取消观察

取消观察是为了避免组件页面切换过程中多次进行监听。

var unsubscribe = autorun(()=>{
  console.log(observableNumber.get())
})

// 取消观察
unsubscribe()

4. mobx-react

mobx-react 让 Mobx 不用自己订阅和取消订阅,和 react-redux 一样。安装 npm i mobx-react。其原理也是构建一个高阶组件 (mobx-react 提供的)提供订阅和取消订阅功能。

1)类组件使用:

<Provider Store={store}>
	<App/>
</Provider>

@inject("store") // 注入 store 给组件,仅仅指在组件中可以用
@observer // 高阶组件帮你自动监听和取消订阅
class App extends Component {
  // store 通过 this.props 传给组件
}

2)函数式组件使用:

return(
	<div>
		<Observer> // 帮你监听订阅 autorun 和取消订阅
	  	{ // 需要自己引入 store 使用
 	   		()=>{
 	     		return ...
  	  	}
 	 		}
		</Observer>
	</div>
)
posted @ 2025-07-30 17:14  背包の技术  阅读(37)  评论(0)    收藏  举报