我只用了 MobX 不到半年时间, 研究的时间更短, 但是我确实想帮助想用 MobX 的人. 很久之前想写一篇对 Redux 的研究, 但是网上写的很多, 而 MobX 相比较 Redux 更小众, 网上很多资料例如介绍 API 的都是官网的复刻节选, 但我用 MobX 感觉真的很爽, 所以写篇文章帮助初入 MobX 坑的玩家们, 如果写的不对, 也希望各位指正, 更好发展.
本篇小文专注使用这一个方向, 不打算写很多, 因为涉及的确实太多~
适合用 MobX 的项目
我认为能用 redux 的项目就可以用 mobx, 除非需要 redux-saga 完成一些极其复杂的异步状态改变, 都可以完美替代, 一些如微博之类偏社交的整体异步状态并发改变可能很多, 不太适合; 像能分成各个小模块的, 各模块互相联系不是很紧密的复杂项目用 mobx 体验很好. 简言之, 因地制宜, 不要无脑使用 redux, 每个都有适合的环境.
基本知识储备
基本的 API 等详细介绍就略过了, 网上还比较多, 也可以移步 MobX 中文官网 https://cn.mobx.js.org/ , 安装 MobX 和 mobx-react 还有装饰器和对应的 babel 网上资料也很清晰.
想更好的理解 MobX 可以找找网上的手写 MobX 教程, 也有助于理解本篇文章(PS: 很多 API 手写起来比想象的简单, 简单说来就是把一个普通的深层对象通过递归层层绑定, 变成 observable 的对象, 实现最小细粒度的依赖收集)
另外, 值得一提的就是 MobX5 使用的 proxy,MobX4 以下用的 Object.defineProperty, 还是有点区别的, 不多说了
结合 MVP 思想使用
官网的图
相比较 redux 状态管理库, 这种单向流真的清晰容易理解, 同时我们团队做了进一步简化, 不用 Actions 触发, 直接修改状态 state, 但对其做了一些约定, 使得代码量进一步降低
我们团队使用 mvp 思想, 这里的 mvp 其实类似安卓的 mvp 思想, 是 mvc 的兄弟, mvp 优点是数据和视图分得很开, 缺点是如果逻辑多的话, presenter 可能会很重, 但是采用 MobX 的话会好很多, 大量受观察的数据可以少写些逻辑. MobX 写起来很简单(代码比 redux 少太多), 逻辑也比较清晰, 可以在 presenter 里面很快找到数据变动的逻辑
上图就是一个 mvp 思想下的模块, 整个模块: Home 这个 tsx 组件负责 View, 在 constructor 函数里面 new 实例化 Presenter.ts 这个控制器(最好是这样做, 状态组件可以复用),presenter 负责整个的数据处理逻辑, 同时引入 Home 的子组件要把实例化后的 presenter 传入, 大体就是这些
不使用严格模式的话, 不会有 Actions 而是直接改 observable 的 state, 下面是占出现率 99% 的 API
@observer: 用在 react 的 view 层的组件上方, 变成可观察的
@observable: 把一个变量变成可观察的
@computed: 类似于 vue, 收集 observable 的变化而变化
autorun: 包裹的函数先自动执行一次, 里面检测到有依赖变动, 自动执行
toJS(value, options?)
: 把 observable 的对象变回原生 JS 对象的函数(实际用的地方很少, 但需要知道, 如果是用 4 版本一下的还是要特别注意)
下面用代码简单示意
View 层 GoodsPriceTrackHome.tsx 代码如下:
- @observer
- export default class GoodsPriceTrackHome extends React.Component<any, any> {
- private presenter: GoodsPriceTrackPresenter;
- constructor(props: any, context: any) {
- super(props, context);
- this.presenter = new GoodsPriceTrackPresenter();
- }
- // 简单示意
- render() {
- const {abc,changeAbc} = this.presenter;
- return <div onClick={changeAbc}>
- abc
- </div>
- }
- // 如果有子组件且需要传 presenter 的话
- render() {
- return <Children
- presenter={this.presenter}
- />
- }
控制器这一层 GoodsPriceTrackPresenter.ts 代码如下:
- export default class GoodsPriceTrackPresenter {
- @observable
- public abc: number = 123;
- public changeAbc(){
- this.abc++;
- }
- }
是否及何时使用严格模式
结论: 基本不用严格模式(像示例中直接改了 this.abc), 如果是两三个人协作开发的小项目, 开发过程中基本没有太多交集, 自然不需要约定修改, 大型项目的话, 只有登录等账户全局的一些异步操作需要严格模式 @action 来约束, 其他模块的话, 最多一两个人来负责开发维护, 所以如果基本上是自己负责一个模块或者一个小项目, 就直接用普通模式
注意事项
所有的与服务器通信, 数据变动操作都放在 p(presenter)上, 除了监控 ui 的变化 (如一些自适应之类) 才放在 v(view)上
MobX 体验的一些不足
1. 开发插件
mobx 由于是分布式的状态管理, 所以几个开发插件体验不好, 基本没怎么用, 调试是打断点或者 console, 感觉这样更方便一些
2. 内存泄漏
开发者水平不齐或者无意识的进行不规范的使用, 可能会造成内存泄漏, 用户长时间使用产品造成内存泄漏, 影响用户体验(组件卸载之后, 但是其他引用较乱, 导致某些手观察对象或者闭包无法释放)
3. 侵入性
面向对象的话, 设计较为复杂, 无关大量数据绑定太多, 也会影响到性能
总结
1. 基本不用严格模式约束, 直接在 Presenter 组件里改状态(但怎么改一定要事先理清思路哈)
2. 相比 redux,MobX 管理状态更简单有效率, 写的代码更少, 做项目效率更高(但要分项目适不适合)
3. 如果不注意使用规范, 大项目可能会有性能问题(一般是遇不到的)
这篇文章我还会经常去完善更新, 因为状态库涉及太多, 讲得比较草率, 很多都点到即止了
来源: https://juejin.im/post/5c2e22b6e51d4532330224fe