Mobx6 了解及 RootStore使用

133 阅读3分钟

概念

属性,完整的对象,数组,Maps 和 Sets 都可以被转化为可观察对象。 使得对象可观察的基本方法是使用 makeObservable 为每个属性指定一个注解。 最重要的注解如下:

  • observable 定义一个存储 state 的可追踪字段。
  • action 将一个方法标记为可以修改 state 的 action。
  • computed 标记一个可以由 state 派生出新的值并且缓存其输出的 getter。

像数组,Maps 和 Sets 这样的集合都将被自动转化为可观察对象。

安装:

MobX可在任何ES5环境(包括浏览器和NodeJS)中运行。

MobX 有两种 React 绑定方式,其中 mobx-react-lite仅支持函数组件,mobx-react 还支持基于类的组件。可以使用Yarn、NPM、CDN集成MobX到您的项目中:

Yarn: yarn add mobx

NPM: npm install --save mobx

工作流程:

图片.png

优点

2.Mobx与redux的区别

  • Mobx写法上更偏向于OoP
  • 对一份数据直接进行修改操作,不需要始终返回一个新的数据
  • 并非单一store,可以多store。
  • Redux默认以avaseript原生对象形式存储数据,而Mobx使用可观察对象,

优点:

a.学习成本小

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

缺点:

a.过于自由:Mobx提供的约定及模版代码很少,代码编写很自由,如果不做一些约

定,比较容易导致团队代码风格不统一

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

例子

代码版本:mobx6、React 18

采用 RootStore 实现对数据整合处理,最简单的数据增减1计算,数据存储在mobx内

文件目录:

图片.png

src下的store存储数据、Counter.js组件

src/index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
// antd汉化
import { ConfigProvider } from 'antd'
import zhCN from 'antd/locale/zh_CN';

import Counter from './views/Counter';
import { RootStoreProvider } from "./store"



const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <>
        <ConfigProvider locale={zhCN}>
            <RootStoreProvider>
                <Counter />
            </RootStoreProvider>
        </ConfigProvider>
    </>
);

store/index.js

import CounterStore from "./countStore";
import { createContext, useContext } from "react";


class RootStore {
    constructor() {
        // 这里还可以继续添加多模块store
        this.counterStore = new CounterStore()
    }
}

// store实例创建
const rootStore = new RootStore()

// react 上下文获取
const RootStoreContext = createContext()

export const RootStoreProvider = ({ children }) => {
    return (
        <RootStoreContext.Provider value={rootStore}>
            {children}
        </RootStoreContext.Provider>
    )
}

export const useRootStore = () => {
    return useContext(RootStoreContext)
}

store/countStore.js

import { action, makeObservable, observable } from 'mobx'

export default class CounterStore {
    constructor() {
        this.count = 0
        makeObservable(this, {
            count: observable,
            increment: action.bound,
            decrement: action.bound
        })
    }
    increment() {
        this.count += 1
    }
    decrement() {
        this.count -= 1
    }
}

views/Counter.js

import style from "styled-components";
import { Button } from "antd";
import { observer } from 'mobx-react-lite';
import { useRootStore } from "@/store"

const CountDiv = style.div`
    padding:20px;
    .count, .ant-btn{
        margin: 10px;
    }
`

function Counter() {
    const { counterStore } = useRootStore()
    const { count, increment, decrement } = counterStore
    return (
        <CountDiv>
            <div className="count">count: {count}</div>
            <Button onClick={() => increment()} type="primary">增加</Button>
            <Button onClick={() => decrement()} type="primary">减少</Button>
        </CountDiv>
    )
}

// observer 视图更新 
export default observer(Counter)

运行结果:

图片.png

RootStore

在react项目内,使用 RootStore是通过React context 插入到组件树中,所以在store/index.js文件内,使用RootStore对mobx的store进行统一管理,不再需要给组件淡出传递属性等

内部采用了 React.createContext()上下文传值,并使用 useContext获取上下文数据等多种操作完成,同时 React.createContext() 也被用到redux传值等

总结:

状态变化更新视图的必要条件

  1. 状态必须被标记为 observable
  2. 更改状态的方法必须被标记为 action
  3. 组件必须通过 observer 方法包裹