服务端阅读 05月31日 15:55
大型前端应用中 MobX Store 应该如何拆分和协作?
大型应用里用 MobX,关键不是“建一个 store 然后全局导出”,而是把状态边界划清楚。页面越多,store 越容易变成杂物间:登录信息、列表缓存、弹窗状态、错误提示、持久化逻辑全塞一起,短期写得快,后期任何改动都像拆炸弹。比较稳的做法是用 RootStore 管组合关系,业务 Store 管自己的数据和动作,跨模块协作只通过少数明确入口发生。推荐的基本结构RootStore 不应该写太多业务逻辑,它更像装配层。UserStore、ProductStore、CartStore 等模块各自维护领域状态,构造时拿到 root 或必要依赖。也方便测试时替换依赖。class RootStore { userStore: UserStore; cartStore: CartStore; constructor(api: ApiClient) { this.userStore = new UserStore(api.user); this.cartStore = new CartStore(api.cart, this.userStore); makeAutoObservable(this, {}, { autoBind: true }); }}class CartStore { items: CartItem[] = []; constructor(private api: CartApi, private userStore: UserStore) { makeAutoObservable(this, {}, { autoBind: true }); } get total() { return this.items.reduce((s, i) => s + i.price * i.count, 0); }}哪些状态该进 MobX长期共享、会被多个页面读取、需要派生计算的状态适合进 MobX,比如用户、权限、购物车、筛选条件、实体缓存。只属于一个组件的输入框临时值,不必为了“统一管理”强行进全局 store。取舍点在生命周期和共享范围:短命状态适合本地,长期状态适合 store。持久化也不要一把梭。登录 token、主题、语言可以落 localStorage;大量实体数据更适合接口缓存。autorun 自动保存很方便,但要防抖、过滤敏感字段,并在 store 销毁时清理 disposer。追问单一 RootStore 和多个业务 Store 怎么取舍?小项目用一个 store 没问题,文件少、调试直接。大型应用更适合多个业务 Store,因为团队可以按领域并行维护,测试也更容易隔离。代价是跨 store 依赖会变复杂,所以 RootStore 要控制装配关系,不能让每个 store 随意 import 另一个单例。边界是:当一个文件开始同时处理三个以上业务域时,就该拆了。Store 之间通信能不能用事件总线?能用,但一般不推荐作为首选。事件总线让依赖看起来松,实际调试时很难知道某个状态是谁改的。更稳的方式是构造函数注入依赖,或者由上层 action 编排多个 store。事件总线适合埋点、全局通知这类不要求强业务一致性的场景,别拿它处理订单和权限这种核心流程。computed 越多性能越好吗?不是,computed 适合表达由 observable 推导出的稳定结果,并且只有被观察时才有缓存价值。把所有函数都改成 computed 会让依赖关系变难读,还可能因为返回新数组导致下游重复渲染。大型列表里常见做法是把筛选条件和原始数据分开,computed 只做必要派生。边界是:它应该没有副作用,也不应该偷偷发请求或修改状态。get visibleProducts() { return this.products.filter(p => p.category === this.category);}大型应用如何避免 Store 变成上帝对象?先按业务能力拆,而不是按 observable、action、computed 这种技术类型拆。比如 user、order、payment 这样的领域边界,比“actions 文件夹里塞一切”更容易维护。每个 store 暴露少量动作,内部字段能私有就私有,组件不要绕过 action 到处改。踩坑点是为了省事把 root 传给所有 store,最后每个 store 都能访问全世界。MobX Store 怎么测试才不脆?优先测试业务动作和派生结果,不要测试 MobX 内部实现。API 依赖用 fake client 注入,异步 action 等待结束后断言 observable 状态即可。组件测试只验证 UI 是否响应 store 状态变化,没必要把真实 RootStore 全挂上。边界在于:如果一个测试需要同时准备五个 store 才能跑,通常说明业务逻辑拆分还不够清楚。