前言
- mobx-react-lite仅支持函数组件,mobx-react还支持类组件
- 安装: npm i mobx mobx-react mobx-react-lite
基本使用
-
store/index.ts
import { makeAutoObservable } from 'mobx' export default class useMobxStore { count: number = 0 // 初始化状态数据 constructor() { // 对初始化数据进行响应式处理 makeAutoObservable(this) } // 设置改变初始化数据方法 addCount = () => { this.count++ } } -
组件内部使用
import React from 'react' import { observer } from 'mobx-react-lite' // 从 mobx-react-lite 内部引入 observer 让 mobx 与 react 进行关联 import useMobxStore from '@/store' const MobxDemo = () => { return ( <div> <h2>{useMobxStore.count}</h2> <button onClick={useMobxStore.addCount}>+1</button> </div> ) } export default observer(MobxDemo) // 对组件进行mobx与react的关联绑定
异步action
方式1: 使用 action 对它们进行包装
import { action, makeAutoObservable } from 'mobx'
class Store {
githubProjects = []
state = 'pending' // 'pending', 'done' or 'error'
constructor() {
makeAutoObservable(this)
}
fetchProjects() {
this.githubProjects = []
this.state = 'pending'
fetchGithubProjectsSomehow().then(
action('fetchSuccess', res => {
const filteredProjects = somePreprocessing(res)
this.githubProjects = filteredProjects
this.state = 'done'
}),
action('fetchError', error => {
this.state = 'error'
})
)
}
}
方式2: 由 makeAutoObservable 自动包装为 action
如果 Promise 的处理函数是类的字段,它们将由 makeAutoObservable 自动包装为 action
import { makeAutoObservable } from 'mobx'
class Store {
githubProjects = []
state = 'pending' // 'pending', 'done' or 'error'
constructor() {
makeAutoObservable(this)
}
fetchProjects() {
this.githubProjects = []
this.state = 'pending'
fetchGithubProjectsSomehow().then(this.projectsFetchSuccess, this.projectsFetchFailure)
}
projectsFetchSuccess = res => {
const filteredProjects = somePreprocessing(res)
this.githubProjects = filteredProjects
this.state = 'done'
}
projectsFetchFailure = error => {
this.state = 'error'
}
}
方式3: await + runInAction
import { runInAction, makeAutoObservable } from 'mobx'
class Store {
githubProjects = []
state = 'pending' // 'pending', 'done' or 'error'
constructor() {
makeAutoObservable(this)
}
async fetchProjects() {
this.githubProjects = []
this.state = 'pending'
try {
const res = await fetchGithubProjectsSomehow()
const filteredProjects = somePreprocessing(res)
// 修改状态的时候外面包裹runInAction
runInAction(() => {
this.githubProjects = filteredProjects
this.state = 'done'
})
} catch (e) {
runInAction(() => {
this.state = 'error'
})
}
}
}
方式4: flow + generator
import { flow, makeAutoObservable, flowResult } from 'mobx'
class Store {
githubProjects = []
state = 'pending'
constructor() {
makeAutoObservable(this, {
fetchProjects: flow
})
}
// 注意星号, 这是一个 generator 函数
*fetchProjects() {
this.githubProjects = []
this.state = 'pending'
try {
// Yield 代替 await.
const res = yield fetchGithubProjectsSomehow()
const filteredProjects = somePreprocessing(res)
this.state = 'done'
this.githubProjects = filteredProjects
} catch (error) {
this.state = 'error'
}
}
}
const store = new Store()
const res = await flowResult(store.fetchProjects())
计算属性
计算属性需要用 get 开头然后接函数名,并且mobx规定计算属性必须要有返回值
-
store/index.ts
import { makeAutoObservable } from 'mobx' export default class useMobxStore { list = [1, 2, 3, 4, 5, 6] constructor() { makeAutoObservable(this) } // 定义一个计算属性 get filterList() { return this.list.filter((item) => item > 4) } } -
组件内部使用
import React from 'react' import { observer } from 'mobx-react-lite' import store from '@/store' const { useMobxStore } = store const MobxDemo = () => { return ( <div> {/* 计算属性 */} <div>{useMobxStore.filterList.join('~')}</div> </div> ) } export default observer(MobxDemo)
模块化
-
store/index.ts
import React from 'react' import useMobxStore from './modules/mobxDmeo' class RootStore { useMobxStore: useMobxStore constructor() { // 对引入进行来的子模块进行实例化操作,并挂载到RootStore上 this.useMobxStore = new useMobxStore() } } // 实例化操作 const rootStore = new RootStore() // 这里可以使用React context 完成统一方法的封装需求 const context = React.createContext(rootStore) // 封装useStore方法,业务组件调用useStore方法便就可以直接获取rootStore const useStore = () => React.useContext(context) export default useStore -
组件内统一使用
import React from 'react' import { observer } from 'mobx-react-lite' import useStore from '@/store' const MobxDemo = () => { /* 注意 此处解构写道store一级即可,如果解构到store下面一级的属性级,则会破坏响应式数据 */ const { useMobxStore } = useStore() return ( <div> <h2>{useMobxStore.count}</h2> <button onClick={useMobxStore.addCount}>+1</button> {/* 计算属性 */} <div>{useMobxStore.filterList.join('~')}</div> <button onClick={useMobxStore.addList}>点我数组添加内容</button> </div> ) } export default observer(MobxDemo)
数据持久化
安装: npm i mobx-persist-store
import { makeAutoObservable } from 'mobx'
import { makePersistable } from 'mobx-persist-store' // 引入makePersistable方法进行持久化存储
export default class useMobxStore {
count: number = 0
constructor() {
// 响应式处理
makeAutoObservable(this)
// 数据持久化存储
makePersistable(this, {
name: 'mobxDemo', // 存储到localStorage当中的key值是什么
properties: ['count'], // 需要持久化的数据是什么,此数据需要为上面声明了的变量
storage: window.localStorage, // 用哪种方式存储
})
}
addCount = () => {
this.count++
console.log(this.count)
}
}
Mobx与redux的区别
- Mobx写法上更偏向于OOP
- 对一份数据直接进行修改操作,不需要始终返回一个新的数据
- 并非单一store,可以多store
- Redux默认以JavaScript原生对象形式存储数据,而Mobx使用可观察对象
- 优点
- 学习成本小
- 面向对象编程, 而且对 TS 友好
- 缺点
- 过于自由:Mobx提供的约定及模版代码很少,代码编写很自由,如果不做一些约定,比较容易导致团队代码风格不统一
- 相关的中间件很少,逻辑层业务整合是问题
参考
- 官网
- 我搁这敲代码呢: 一篇文章让你快速上手Mobx6
- 千锋教育: 千锋教育2022版React全家桶教程_react零基础入门到项目实战完整版103~107