2-2、使用Mobx管理状态变更

Mobx状态管理基本使用简介

一、Mobx简介

  • mobx简介

    MobX 是一个经过战火洗礼的库,它通过透明的函数响应式编程(transparently applying functional reactive programming - TFRP)使得状态管理变得简单和可扩展(官方)。

    • React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而MobX提供机制来存储和更新应用状态供 React 使用。
    • React 提供了优化UI渲染的机制, 这种机制就是通过使用虚拟DOM来减少昂贵的DOM变化的数量。MobX 提供了优化应用状态与 React 组件同步的机制,这种机制就是使用响应式虚拟依赖状态图表,它只有在真正需要的时候才更新并且永远保持是最新的。

    图示:
    在这里插入图片描述

  • mobx核心要点

    • 定义状态(state)并使其可观察

      // 通过observable可以轻松创建一个可监听、观察的状态
      import {observable} from 'mobx';
      var appState = observable({
          timer: 0
      });
      
    • 创建视图(view)以响应状态的变化

      // observer: 创建观察者,可以监听状态并做出响应、更新
      import {observer} from 'mobx-react';
      
      @observer
      class TimerView extends React.Component {
          render() {
              return (
                  <button onClick={this.onReset.bind(this)}>
                      Seconds passed: {this.props.appState.timer}
                  </button>
              );
          }
         // 更新状态
          onReset() {
              this.props.appState.resetTimer();
          }
      };
      
    • 更新、维护状态(action)

      // action: 行为、动作定义,用于更新状态
      appState.resetTimer = action(function reset() {
          appState.timer = 0;
      });
      
      setInterval(action(function tick() {
          appState.timer += 1;
      }), 1000);
      

二、Mobx的基本使用

  • 创建被监听对象-observable (store)

    • 例如创建一个UserStore,用于管理用户状态

      import { observable, action, computed } from 'mobx';
      
      class UserStore {
        @observable users = null;
        constructor() {
           makeObservable(this); 
        }
      
        @action setUsers = users => {
          this.users = users;
        };
        @action setUser = (user, uid) => {
          if (!this.users) {
            this.users = {};
          }
          this.users[uid] = user;
        };
        @computed get userList() {
          return Object.keys(this.users || {}).map(key => ({
            ...this.users[key],
            uid: key,
          }));
        }
      }
      
      export default UserStore;
      
  • 创建监听者-observer

    • 方式1:使用compose,compose意为可组合(Composeable),即将多个组件进行组合,完成一层套一层的函数调用,简单理解就是“套娃”,便于代码管理和逻辑理解,举个例子说明其作用:

      const multiply = (multiplier) => (multiplicand) =>
          multiplicand * multiplier;
      
      const subtract = (minuend) => (subtrahend) =>
          subtrahend - minuend;
      
      // 相当于:// subtract(2)multiply(4)(3)=3*4-2=10
      const result = compose( 
          subtract(2),
          multiply(4),
      )(3);
      
    • 回到方式1,其具体实现如下

      import React, { Component } from 'react';
      import { observer, inject } from 'mobx-react';
      import { compose } from 'recompose';
      // non decorator usage
      class App extends Component {
        render() {
          const { xxStore } = this.props;
          ...
        }
      }
      
      export default compose(
        observer,
        inject('xxStore')
      )(App);
      
    • 方式2:方式2比较易于理解,通过@observer声明监听者,使用@inject(‘xxStore’)注入要监听的store

      import React, { Component } from 'react';
      import { observer, inject } from 'mobx-react';
      import { compose } from 'recompose';
      // decorator usage
      @inject('xxStore') @observer
      class App extends Component {
        render() {
          const { foo } = this.props;
          ...
        }
      }
      
      export default App;
      
    • 方式3:可以视为方式2的变体

      import React, { Component } from 'react';
      import { observer, inject } from 'mobx-react';
      import { compose } from 'recompose';
      const APP = inject("xxStore")(
          observer( (props:any) => {
             return (...);
          })
      )
      
    • 如果不需要联动store,则使用更为简单

      import React, { Component } from 'react';
      import { observer } from 'mobx-react';
      
      // non decorator usage
      class App extends Component {
        ...
      }
      export default observer(App);
      ------------------------------------------------------
      
      // decorator usage
      @observer class App extends Component {
        ...
      }
      export default App;
      
  • 多个被监听store的组合

    在实际开发中,往往是多个组件之间的复杂状态交互,未来控制更细致粒度的更新,优化性能,就必须将多个store进行组合,统一管理,边缘组件之间的信息流通,状态管理。比如组件A依赖组件B的某个操作设置是否可见,是否更新状态等,组合多个组件的store,基本做法如下:

    • 创建多个xxStore,

    • 例如UserStore:标识用户,用于用户列表的用户对象存储

      import { observable, action, computed } from 'mobx';
      
      class UserStore {
        @observable users = null;
        constructor(rootStore) {
          this.rootStore = rootStore;
        }
      
        @action setUsers = users => {
          this.users = users;
        };
        @action setUser = (user, uid) => {
          if (!this.users) {
            this.users = {};
          }
          this.users[uid] = user;
        };
        @computed get userList() {
          return Object.keys(this.users || {}).map(key => ({
            ...this.users[key],
            uid: key,
          }));
        }
      }
      
      export default UserStore;
      
    • MessageStore消息存储库、管理分页功能的另外一个属性:limit,用于管理分页限制,当然这里仅仅是做例子,实际开发需要结合需要,至少这里不需要考虑复杂的其他因素。

      import { observable, action, computed } from 'mobx';
      
      class MessageStore {
        @observable messages = null;
        @observable limit = 5;
      
        constructor(rootStore) {
          this.rootStore = rootStore;
        }
      
        @action setMessages = messages => {
          this.messages = messages;
        };
      
        @action setLimit = limit => {
          this.limit = limit;
        };
      
        @computed get messageList() {
          return Object.keys(this.messages || {}).map(key => ({
            ...this.messages[key],
            uid: key,
          }));
        }
      }
      
      export default MessageStore;
      
    • 使用RootStore组合多个xxStore,RootStore的核心作用就是管理不同的store,将不同的store进行组合,然后统一暴露,在整个dom的生命周期提供统一的状态池。

      import UserStore from './userStore';
      import MessageStore from './messageStore';
      
      class RootStore {
        constructor() {
          this.userStore = new UserStore(this);
          this.messageStore = new MessageStore(this);
        }
      }
      
      const rootStore = new RootStore();
      export default rootStore;
      
    • 使用方式/src/index

      import {rootStore} from "@/pages/RootStore";
      
      const root = ReactDOM.createRoot(
        document.getElementById('root') as HTMLElement
      );
      root.render(
            <Provider {...rootStore}>
                ...
            </Provider>,
      );
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玉言心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值