概念
属性,完整的对象,数组,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
工作流程:
优点
2.Mobx与redux的区别
- Mobx写法上更偏向于OoP
- 对一份数据直接进行修改操作,不需要始终返回一个新的数据
- 并非单一store,可以多store。
- Redux默认以avaseript原生对象形式存储数据,而Mobx使用可观察对象,
优点:
a.学习成本小
b.面向对象编程,而且对TS 友好
缺点:
a.过于自由:Mobx提供的约定及模版代码很少,代码编写很自由,如果不做一些约
定,比较容易导致团队代码风格不统一
b. 相关的中间件很少,逻辑层业务整合是问题。
例子
代码版本:mobx6、React 18
采用 RootStore 实现对数据整合处理,最简单的数据增减1计算,数据存储在mobx内
文件目录:
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)
运行结果:
RootStore
在react项目内,使用 RootStore是通过React context 插入到组件树中,所以在store/index.js文件内,使用RootStore对mobx的store进行统一管理,不再需要给组件淡出传递属性等
内部采用了 React.createContext()上下文传值,并使用 useContext获取上下文数据等多种操作完成,同时 React.createContext() 也被用到redux传值等
总结:
状态变化更新视图的必要条件
- 状态必须被标记为 observable
- 更改状态的方法必须被标记为 action
- 组件必须通过 observer 方法包裹