前言
在reactjs中,父子组件,同级组件间的状态传递只能通过props传递,如果需要传递的变量过多,就会导致项目混乱难以维护,并且容易产生意想不到的bug。所以我们需要一个能管理全局状态的工具,如redux,mobx这类的就是为了解决这个问题。
mobx基本概念
- 使得状态管理变得简单可扩展。
- 状态:是驱动应用的数据。
- 衍生:源自状态并且不会再有任何进一步的相互作用的东西就是衍生。
- 动作:是任一一段可以改变状态的代码。
mobx/mobx-react详解
主要api
- observable:mobx属性设置可观察状态
- action:mobx属性定义状态何时更新
- compute:mobx属性监听自动更i新的值
- provider:mobx-react的属性用来与mobx连接
- observer:mobx-react的属性将react组件转变为响应式
- inject:mobx-react的属性将mobx定义的实例注入到react组件
基本配置
1.安装mobx
//在react中使用mobx需要安装react-mobx
npm install mobx --save
npm install react-mobx --save
2 直接在react组件中定义
import React from "react";
import ReactDOM from "react-dom";
import { observable, action } from "mobx";
import { observer } from "mobx-react";
// 创建状态值
let appState = observable({ timer: 0 });
// action 来控制状态值
setInterval(
action(() => {
appState.timer += 1;
}),2000);
appState.resetTimer = action(() => {
appState.timer = 0;
});
// 让组件称为响应式组件
let TimeView = observer(({ appState }) => {
return (
<div className="App">
<h1>Time:
: {appState.timer}</h1>
<button onClick={appState.resetTimer}>reset timer</button>
</div>
);
});
//让组件称为响应式组件
let TimeView2 = observer(({ appState }) => {
return (
<div className="App">
<h1>Time: {appState.timer}</h1>
</div>
);
});
//对比不是响应式组件 只会有初期值
let TimeView3 = ({ appState }) => {
return (
<div className="App">
<h1>Time: {appState.timer}</h1>
</div>
);
};
let App =()=>{
return (
<div>
<TimeView appState={appState} />
<TimeView appState={appState} />
<TimeView3 />
</div>
)
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
基本api使用示例
mobx的核心api分为四类,定义状态(observable),响应状态(autorun,computed),修改状态(action),辅助函数
1.mobx-react
- Provider:mbox-react中一个组件,使用react中的上下将store中的状态传递给子组件
//当作react组件使用一般放在项目的最外侧组件
<Provider {...store}>
<App />
</Provider>
- observer:转换react组件定义的装饰器, 将react组件或独立渲染的函数 变成响应式组件, 在一些可观察的值发生变化的时候 ,这个响应式组件会追踪render 和自动re-render。
//在组件的外侧使用装饰
@observer
class Demo extends Component{}
//正常使用
observable(class Demo extends Component{});
注意:当 observer 需要组合其它装饰器或高阶组件时,请确保 observer 是最深处(第一个应用)的装饰器,否则它可能什么都不做。
- inject:用于将store注入当前组件。(将组件连接到提供的 stores)
//装饰器使用方式
@inject("appStore")
@observer
class Demo extends Component{}
//正常使用
inject("appStore")(observable(class Demo extends Component{}));
使用步骤:1.使用observer定义可观察组件 2.使用Provider连接所有的stores 3.使用inject在组件中注入相关stores 4.使用stores中定义的状态
2.mobx
- observable:定义可观察状态,其值的类型可以为基本和引用类型。
//装饰器使用
@observable classProperty = value
//创建一个 observable 的盒子,它用来存储value的 observable 引用。使用 get() //方法可以得到盒子中的当前value,而使用 set() 方法可以更新value。
observable.box(value, options?)
- compute:创建计算值
注:每当读取computed值时,如果其依赖的状态或其他computed值未发生变化,则使用上次的缓存结果,以减少计算开销,对于复杂的computed值,缓存可以大大提高性能。
const ca = computed(() => {
return 10 * store.a;
});
- autorun:用于定义响应函数,其类型定义如下(已简化)
autorun(reaction: () => any): IReactionDisposer;
computed与autorun相似,他们都会在依赖的状态发生变化时会重新运行,不同之处是computed接收的是纯函数并且返回一个计算值,这个计算值在状态变化时会自动更新,计算值可以在autorun中使用。
const store = observable({
num: 1
});
const totalPrice = computed(() => {
return 42 * store.num;
});
autorun(() => {
console.log("数量*价格"+`${store.num} * 42= ${totalPrice.get()}`);
});
// 1 * 42 = 42
store.num += 1;
// 2 * 42 = 84
store.nub += 1;
- actions:任何应用都有动作。动作是任何用来修改状态的东西。 使用MobX你可以在代码中显式地标记出动作所在的位置(修改状态)
//定义强制修改状态只能用action
configure({
enforceActions: "always"
});
const store = observable({
num: 1
});
const totalPrice = computed(() => {
return 42 * store.num;
});
autorun(() => {
console.log("数量*价格"+`${store.num} * 42= ${totalPrice.get()}`);
});
// 1 * 42 = 42
const increaseNum = action(() => {
store.num += 1;
})
increaseNum()
装饰器配置
1 设置项目允许装饰器
- 安装react-app-rewired
npm i react-app-rewired --save
- 创建config-overrides.js
module.exports = override()
- 安装插件customize-cra
npm i customize-cra
- 配置允许使用装饰器
const {addDecoratorsLegacy()} = require("customize-cra")
module.exports = override(addDecoratorsLegacy())
2 创建store实例
- 在src目录下新建store目录
- 在store目录新建index.js文件
- 如果项目很小直接在index.js处理store,否则可以分多个文件定义
import {observable,action,computed} from 'mobx';
class AppStore{
@observable list=[]
@action
setList(array){
this.list=array
}
}
export default new AppStore();
连接react
- provide与indject配合使用
- 在根组件中使用provide
import React, { Component } from 'react';
import ReactDom from 'react-dom';
import Store from "./store";
import {Provider} from "mobx-react"
ReactDom.render(
<Provider {...Store}>
****
</Provider>
)
转换组件为响应式
- 新建组件引入
import React, { Component } from 'react';
import Store from "./store";
import {observer,inject} from "mobx-react"
@inject("AppStore")
@observer
class Test extends Component {
render() {
return (
<div>
</div>
);
}
}
export default Test;
使用store中定义的状态
//注入后store中存储的值会挂载到当前组件的props上
this.props.AppStore....
总结
在react的项目中redux是官方推荐使用的状态管理,但是在中小型项目中使用redux,我觉的太过笨重了,于是就采用了mobx这个状态管理库,mobx的简单,易用,可扩展性让react的状态设计变得如此简单方便。另外如果你想要快速掌握mobx,只需要牢记他的核心:任何源自应用状态的东西都应该自动地获得。
注:本文参考mobx官方文档