阅读 327

Reactjs系列五状态管理mobx初识

前言

在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官方文档

关注下面的标签,发现更多相似文章
评论