前言
在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,只需要牢记他的核心:任何源自应用状态的东西都应该自动地获得。