搞懂mobx只需要这一篇文章

Mobx
1、Mobx介绍

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

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

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

(4)Mobx写法上更偏向于OOP 对一份数据直接进行修改操作,不需要始终返回一个新的数据 并非单一store,可以多store。

2、Mobx的优缺点
优点:

​ a. 学习成本小

​ b. 面向对象编程, 而且对 TS 友好

缺点:

​ a. 过于自由:Mobx提供的约定及模版代码很少,代码编写很自由,如果不做一些约 定,比较容易导致团队代码风格不统一

​ b. 相关的中间件很少,逻辑层业务整合是问题

3、Mobx的相关Api
(1)observable 和 autorun

observable 指定要观察的变量,对于常量使用observable.box()方式观察,对象数组可以直接使用observable()

autorun 当观察的变量变化后,会调用它的回调函数

import { observable, autorun } from 'mobx';
const value = observable.box(0);
const number = observable.box(100);
autorun(() => {
console.log(value.get());
});
value.set(1);
value.set(2);
number.set(101);
//0,1,2。 // autorun 使用到才能被执行
//只能是同步,异步需要处理
//观察对象,通过map
const map = observable.map({ key: "value"});
//map.set("key", "new value");
//map.get("key")

//观察对象,不通过map
const map = observable({ key: "value"});
// map.key map.key="xiaoming"
//观察数组
const list = observable([1, 2, 4]);
list[2] = 3;
(2) action和runInAction

action:在严格模式下必须使用anction 修饰的方法来修改observable包裹的变量

runInAction:它的执行时机是在下一个事件循环tick,即下一个Promise被resolve或reject后,

在严格模式下,异步数据操作需要用runInAction包裹,否则会导致状态更新不成功。

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

when:在符合条件的时候才会执行回调函数,并且只会执行一次

import {observable, when} from 'mobx';
const count = observable.box(10)
when(count>11,()=>{console.log(count)})
setInterval(()=>{
  count++
},1000)

reaction:与autorun类似,observable 包裹的变量变化后就会执行相关的回调,但是在初始的时候不会执行

import {
  observable,  
  configure,
  runInAction,
  action,
  reaction,
 } from 'mobx';
configure({enforceActions:'always'})

class Store {
  @observable number:number = 0;
  @observable price:number = 0;
  @observable amount:number = 0

  @action updateNumberPrice = (num:number,price:number) => {
    this.number = num
    this.price = price
  }
  @action updateAmount = (newValue:number) => {
    this.amount = newValue;
  }

}


const store = new Store()
reaction([store.number,store.price],()=>{
  const amount = store.number * store.price
  store.updateAmount(amount)
})
4、mobx-react的使用

(1)react 组件里使用 @observer observer 函数/装饰器可以用来将 React 组件转变成响应式组件。

(2) 可观察的局部组件状态 @observable 装饰器在React组件上引入可观察属性。而不需要通过 React 的冗长和强制性的 setState 机制来管 理。

import {observer} from "mobx-react"
import {observable} from "mobx"
@observer class Timer extends React.Component {
  @observable secondsPassed = 0
  componentWillMount() {
    setInterval(() => {
      this.secondsPassed++
    }, 1000)
  }//如果是严格模式需要加上 @action 和 runInAction
  //一个新的生命周期钩子函数 componentWillReact
  //当组件因为它观察的数据发生了改变,它会安排重新渲染,
  //这个时候 componentWillReact 会被触发
  componentWillReact() {
    console.log("I will re-render, since the todo has changed!");
  }
  render() {
    return (<span>Seconds passed: { this.secondsPassed } </span> )
  }
}
ReactDOM.render(<Timer />, document.body)
5、装饰器的配置
npm i @babel/core @babel/plugin-proposal-decorators @babel/preset-env

创建.babelrc

{
  "presets": [
    "@babel/preset-env"
  ],
    "plugins": [
      [
        "@babel/plugin-proposal-decorators",
        {
          "legacy": true
        }
      ]
    ]
}
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())

创建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())

安装依赖

npm i customize-cra react-app-rewired

修改package.json

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  "eject": "react-app-rewired eject"
  }

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值