MobX是什么
mobx通过透明的函数响应式编程(transparently applying functional reactive programming - TFRP)使得状态管理变得简单和可扩展。
核心原理
利用defineProperty(<=v5)或Proxy(v6)拦截对象属性的变化,实现数据的Observable,在 get 中依赖收集,set 中触发依赖绑定的监听函数。
原则
事件触发action更新 observable 状态
observable 状态的变更会被精确地传送到中所有依赖于它们的计算和副作用里。
安装
mobx包,提供了 MobX 所有的与具体框架平台无关的基础 Api
react-mobx包,针对react开发提供的包
$ npm i mobx react-mobx
在 react 开发中,如果只使用函数式组件,不使用类组件,那么可以将 mobx-react 替换为轻量的包 mobx-react-lite
$ npm i mobx mobx-react-lite
使用
store
官方推荐使用类的方式声明store
使用 类+makeObservable 需要手动声明注解
const {
observable,
action,
computed,
makeObservable,
autorun,
flow,
} = require("mobx");
class CountStore {
count;
total;
constructor(count) {
this.count = count;
makeObservable(this, {
count: observable,
total: observable,
doubleCount: computed,
addCount: action,
addTotal: action,
fetchData: flow,
});
}
get doubleCount() {
console.count("执行次数是:");
return this.count * 2;
}
addCount = () => {
this.count++;
};
addTotal = () => {
this.total++;
};
*fetchData() {
const res = yield fetch("/v1/mock");
}
}
const counter = new CountStore(0);
// 每当关联的值发生变化时,自动运行副作用。
autorun(() => {
console.log("autorun", counter.doubleCount);
});
console.log("doubleCount ", counter.doubleCount); // 不会重新计算
counter.addCount();
counter.addTotal();
-
observable: 属性,完整的对象,数组,Maps 和 Sets 都可以被转化为可观察对象。
-
action:action 就是任意一段修改 state 的代码
-
flow:处理异步操作,makeAutoObservable会把 generators 自动推断成 flow
-
computed:计算值可以用来从其他可观察对象中派生信息。 计算值采用惰性求值,会缓存其输出,并且只有当其依赖的可观察对象被改变时才会重新计算。 它们在不被任何值观察时会被暂时停用。
使用 类+makeAutoObservable
makeAutoObservable就像是加强版的makeObservable,在默认情况下它将推断所有的属性。也可以重写注解的默认行为
- 属性会成为
observable getters会成为computedsetters会成为actionfunction会成为autoActiongenerator functions会成为flow
import { makeAutoObservable } from "mobx";
class CountStore {
count;
constructor(count) {
this.count = count;
makeAutoObservable(this);
}
get doubleCount() {
return this.count * 2;
}
addCount = () => {
this.count++;
};
*fetchData() {
const res = yield fetch("/v1/mock");
}
}
export default CountStore;
集成React
MobX 可以独立于 React 运行, 但是他们通常是结合在一起使用
Mobx使用单向数据流,利用 action 改变 state ,每当关联的值发生变化时,自动重新渲染组件
HOC方式,使用 observer 包裹React Component
import React from "react";
import { Button } from "antd";
import { makeAutoObservable } from "mobx";
import { observer } from "mobx-react";
class CountStore {
count;
constructor(count) {
this.count = count;
makeAutoObservable(this);
}
get doubleCount() {
return this.count * 2;
}
addCount = () => {
this.count++;
};
}
export const store = new CountStore(0);
const Demo1 = () => {
const { count, addCount } = store;
return <Button onClick={() => addCount()}>{count}</Button>;
};
export default observer(Demo1);
使用hooks useObserver
import React from "react";
import { useObserver } from "mobx-react";
import { Button } from "antd";
import { store } from "./demo1";
const Demo2 = () => {
return useObserver(() => {
const { doubleCount, addCount } = store;
return <Button onClick={addCount}>{doubleCount}</Button>;
});
};
export default Demo2;
使用<Observer>组件(通常使用在回调组件上)
使用useLocalObservable定义组件内state
import React from "react";
import { Observer, useLocalObservable } from "mobx-react";
import { Button } from "antd";
const Row = ({ render }) => {
return <div>{render()}</div>;
};
const Demo3 = () => {
const localStore = useLocalObservable(() => ({
localCount: 1,
localAddCount() {
this.localCount++;
},
}));
return (
<Row
render={() => (
<Observer>
{() => {
const { localAddCount, localCount } = localStore;
return <Button onClick={localAddCount}>{localCount}</Button>;
}}
</Observer>
)}
/>
);
};
export default Demo3;
与Redux相比
数据是否可变
Redux 期望所有状态更新都是使用不可变的方式。reducer总是返回一个新的状态,而不是改变你的状态,reducer不执行状态突变或依赖对象引用。在原理上禁止使用 mutable方式修改状态。
Mobx使用可变数据结构,使用熟悉的 JavaScript 赋值就行,原则上只能使用action来修改状态,但是也可以直接修改去修改状态,让项目变得更加不可维护。
存储的数据结构
Redux默认是存储的一个原生的JavaScript对象,而MobX则是存储了一个可观察的对象。
哪个更好?
抛开实际项目使用不谈?我认为xxx更好
任何的对比都应在实际项目使用中