如何在mobx-state-tree模型间共享操作?注入模型引用方案咨询
在MobX-State-Tree中跨模型共享操作的几种方案
针对你提出的在AuthModel的login操作中调用UIModel的setGlobalLoading方法的需求,有以下几种实用方案:
方案1:通过getRoot获取根模型访问其他子模型
MST的每个模型实例都可以通过getRoot方法获取到根模型实例,进而访问其他子模型的状态和操作,这是最直接的实现方式:
import { types, getRoot } from "mobx-state-tree"; const UIModel = types .model({ globalLoading: types.boolean, }) .actions((self) => ({ setGlobalLoading(value) { self.globalLoading = value; }, })); const AuthModel = types .model({ userData: types.maybeNull(types.frozen()), }) .actions((self) => ({ login() { // 获取根模型实例,调用UIModel的方法 const root = getRoot(self); root.ui.setGlobalLoading(true); // 后续登录逻辑... // 登录完成后可调用root.ui.setGlobalLoading(false)关闭加载状态 }, })); const RootModel = types.model({ ui: UIModel, auth: AuthModel, }); RootModel.create({ auth: { userData: null }, ui: { globalLoading: false }, });
方案2:将跨模型操作提升到根模型
如果希望降低子模型之间的耦合度,可以把跨模型调用的逻辑封装到根模型的actions中,子模型只需和根模型交互:
import { types, getRoot } from "mobx-state-tree"; const UIModel = types .model({ globalLoading: types.boolean, }) .actions((self) => ({ setGlobalLoading(value) { self.globalLoading = value; }, })); const AuthModel = types .model({ userData: types.maybeNull(types.frozen()), }) .actions((self) => ({ login() { const root = getRoot(self); // 调用根模型封装好的action root.triggerGlobalLoading(true); // 登录逻辑... }, })); const RootModel = types .model({ ui: UIModel, auth: AuthModel, }) .actions((self) => ({ triggerGlobalLoading(value) { self.ui.setGlobalLoading(value); }, })); RootModel.create({ auth: { userData: null }, ui: { globalLoading: false }, });
这种方式下,AuthModel无需感知UIModel的存在,耦合度更低,后续修改UI相关逻辑时也不需要改动AuthModel。
方案3:使用环境(Env)注入
如果你的场景需要在多个模型间共享全局实例,可通过环境注入的方式传递UIModel实例:
import { types, getEnv } from "mobx-state-tree"; const UIModel = types .model({ globalLoading: types.boolean, }) .actions((self) => ({ setGlobalLoading(value) { self.globalLoading = value; }, })); const AuthModel = types .model({ userData: types.maybeNull(types.frozen()), }) .actions((self) => ({ login() { const { ui } = getEnv(self); ui.setGlobalLoading(true); // 登录逻辑... }, })); const RootModel = types.model({ ui: UIModel, auth: AuthModel, }); // 创建实例时传入环境占位,后续注入实际的ui实例 const rootInstance = RootModel.create( { auth: { userData: null }, ui: { globalLoading: false } }, { ui: null } ); rootInstance.env.ui = rootInstance.ui;
这种方式适合复杂场景,但实现相对繁琐,一般优先考虑前两种方案。
内容的提问来源于stack exchange,提问作者Piotr Szlagura
相关产品推荐
相关产品推荐

