如何在纯函数式组件场景下使用MobX并转换Class类型Store?
MobX 函数式实现相关问题解答
1. Class 中 constructor 在函数式场景的对应逻辑
类的constructor作用是初始化类实例的属性、执行实例创建时的必要配置,对应MobX函数式实现的场景分为两种:
- 全局Store场景:对应Store工厂函数的初始化执行逻辑,包括定义初始状态、调用
makeObservable/makeAutoObservable标记可观察属性的过程 - 组件内局部状态场景:对应
useState、useLocalObservable等Hook的初始化执行逻辑
2. 示例Store的函数式转换方案
MobX从6.0版本开始原生支持普通对象定义Store,完全不需要依赖Class语法,你给出的示例可以直接转换为如下的工厂函数写法,功能和原Class实现100%对等:
import { makeAutoObservable } from "mobx" type Todo = { content: string done: boolean } // 工厂函数,等价于原TodoStore类的定义 const createTodoStore = () => { const store = { // 对应原类的todos属性 todos: [] as Todo[], // 对应原类的unfinishedTodoCount计算属性getter get unfinishedTodoCount() { return store.todos.filter(todo => !todo.done).length }, // 对应原类的addTodo方法 addTodo: (todo: Todo) => { store.todos.push(todo) } } // 等价于原constructor内的makeObservable调用,makeAutoObservable会自动识别可观察属性、计算属性和action,无需手动配置 makeAutoObservable(store) // 如果你需要和原示例完全一致的手动配置,可以替换为: // makeObservable(store, { // todos: observable, // unfinishedTodoCount: computed, // addTodo: action // }) return store } // 生成全局单例Store,等价于new TodoStore() export const todoStore = createTodoStore()
3. 全程函数式实现MobX逻辑的可行性
答案是完全可以,MobX本身是与UI框架、编程范式无关的响应式库,不存在必须使用Class的限制:
- 全局Store可以通过上述的工厂函数模式实现,无需任何Class语法
- 组件内的局部MobX状态可以通过
mobx-react-lite提供的useLocalObservableHook实现,写法更简洁,示例如下:
import { observer, useLocalObservable } from "mobx-react-lite" const TodoList = observer(() => { // 直接在组件内定义局部可观察状态 const store = useLocalObservable(() => ({ todos: [] as Todo[], get unfinishedTodoCount() { return this.todos.filter(t => !t.done).length }, addTodo(todo: Todo) { this.todos.push(todo) } })) return ( <div> <div>未完成待办数量:{store.unfinishedTodoCount}</div> <button onClick={() => store.addTodo({ content: '新待办', done: false })}> 新增待办 </button> </div> ) })
注:旧教程大量使用Class编写MobX Store是因为早期MobX的装饰器语法配合Class写法更简洁,目前版本的MobX对普通对象的支持已经非常成熟,两种写法在功能、性能上没有任何差异,可以根据自己的编码习惯自由选择。
内容的提问来源于stack exchange,提问作者Lê Quốc Khánh
相关产品推荐
相关产品推荐

