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>, );
-