一篇文章带你搞定mobx基本使用

2,753 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

介绍

mobx 是状态管理工具,在不少情况下可以代替redux

mobx-react 是做数据分片和数据获取的

安装

1.创建项目后先进行配置文件抽离

npm run eject

2.安装mobx mobx-react

npm i mobx mobx-react

3.配置装饰器 (这里可以自行换成npm)

yarn add babel-plugin-transform-decorators-legacy -D
yarn add @babel/preset-env -D
yarn add babel-plugin-transform-class-properties -D
yarn add @babel/plugin-proposal-decorators -D

4.配置package.josn

  "babel": {
    "plugins": [
      [
        "@babel/plugin-proposal-decorators",
        {
          "legacy": true
        }
      ],
      "transform-class-properties"
    ],
    "presets": [
      "react-app",
      "@babel/preset-env"
    ]
  },

API

computed

作用:

组合观察数据形成一个新观测值,接受一个无参数的函数,必须有返回值,且使用get()方法来获取计算值

函数方式使用:

var foo=computed(function(){return store.string+'/'+store.num}); 
// 当foo变化时调用指定的函数执行操作 foo.observe(函数) 

foo.observe(function(change){console.log(change);})
//可以用来观察监测值,如果有改动就调用函数

注解方式使用:

// 若使用注解,则必须在store类中事先定义好计算值
@computed 
get mixed(){return store.string+'/'+store.num}}; 
// 调用autorun方法,接受一个函数,当函数内部的可观测数据变化时执行函数,此处由于没有使用mixed计算值,则string或者num变化都会输出
autorun(()=>{console.log(return store.string+'/'+store.num);}); 
// 使用mixed计算值,只有该值变化才输出
autorun(()=>{console.log(store.mixed);})

action

action 包装/装饰器只会对当前运行的函数作出反应,而不会对当前运行函数所调用的函数(不包含在当前函数之内)作出反应!

这意味着如果 action 中存在 setTimeout、promise 的 then 或 async 语句,并且在回调函数中某些状态改变了,那么这些回调函数也应该包装在 action 中。可以使用runInAction解决。

@action:修饰的函数必须注意,如果其内部调用了非**@action.bound修饰的异步回调函数,会报错,因为回调函数不在当前上下文环境中,导致this指向错误!可以使用action或者runInAction**包裹代码来解决。

@action.bound:该装饰器将函数上下文绑定了,可以放在其他上下文中依然正确执行,这种写法在将方法传给callback时非常有用

该装饰器保证在其内部修改的变量会等待函数运行结束后再同时触发反应。使用方式:

action("xxx",()=>{…})

observer

属于mobx-react,与react结合使用,在会调用函数导致改变mobx状态的react组件上进行注解

使用方法:

  1. 注解
  2. observer函数:从最外层包裹(用于函数组件)const A = observer((props=>{return <div>1</div>},从render包裹(通用)在react组件的render中进行包裹:return useObserver(()=><div>1</div>)
  3. <Observer>标签:包裹住的值才能相应状态,<Observer>{()=><div>{person.name}</div>}</Observer>

Provider

属于mobx-react,如果当前react项目需要启用mobx管理状态,则必须在根节点上使用Provider标签包裹,同时传递注入对象

在store.js中汇总所有待管理store

import { Provider } from "mobx-react"
import stores from './store'
import {configure} from 'mobx'; // 开启严格模式
configure({enforceActions: true}) // 开启严格模式

class App extends Component{
    render(){
        return(
            <Provider store={...store}>
                <ToDoApp/>
            </Provider>
        )
    }
}

inject

属于mobx-react,对当前的react组件进行注入store,以便访问可观察值,注入的值在this.props

@inject('todoList')
class ToDoApp extends Component{
    render(){
        return (
            <div>
                <TodoListView todoList={this.props.todoList}/>
            </div>
        );
    }
}

示例:

import { observable, action, computed } from "mobx"; 

class CountStore {
  @observable a = 1;
  b = 2; 
  @action  // 注意如果使用普通函数,则必须写成:@action.bound,函数中的this才可以正确指向
  add = () => {
    this.a++; 
    this.b++; 
  };

  @computed get newNum() {
    return this.a + this.b;
  }
}

const countStore = new CountStore();
export default countStore;

import { observer } from "mobx-react";
import { action } from "mobx";
import React from "react";
import "./styles.css";

@observer
class App extends React.Component {
  add2 = action(() => {
    this.props.store.a += 111; 
    this.props.store.b += 111;
  });

  render() {
    console.log(this.props);
    return (
      <div className="App">
        <div>{this.props.store.a}</div>
        <div>{this.props.store.b}</div>
        <div>{this.props.store.newNum}</div>
        <button onClick={this.props.store.add}>按钮</button>
        <button onClick={this.add2}>按钮</button>
      </div>
    );
  }
}

export default App;

这篇文章只是最基础的使用