2.6 KiB
mobx是什么
MobX 负责页面上会变化的状态。mobx-keystone 负责可以保存、比较和恢复的实体。页面组件只负责渲染,不存放业务状态。
目录
页面状态
ViewModel 里需要触发重渲染的字段标成 observable,修改这些字段的方法标成 action。组件用 mobx-react-lite 的 observer 包起来,字段变化后才会重画。
SecurityViewModel 的 errorMessage、isLoading 就是页面状态。它们跟着这一次打开的登录页,所以这个类标 @injectable('Transient')。
普通字段不用 observable。不会显示在界面上的局部变量也不放进 ViewModel。
ViewModel 的生命周期
ViewModel 继承 PageViewModel。页面不自己 new,而调用 useViewModel。
export function useViewModel<T extends PageViewModel>(identifier: new (...args: any[]) => T): T {
const [viewModel] = useState(() => {
const vm = rootContainer.get(identifier);
vm.created();
return vm;
});
useEffect(() => {
viewModel.ready();
const onPageHide = () => viewModel.beforeRefresh();
window.addEventListener('pagehide', onPageHide);
return () => {
window.removeEventListener('pagehide', onPageHide);
viewModel.dispose();
};
}, [viewModel]);
return viewModel;
}
created 在实例取出时调用。ready 在页面挂上后调用,适合开始加载数据,例如 HomeViewModel.ready 去拉项目列表。beforeRefresh 在页面被浏览器收起时调用。离开页面时调用 dispose。
实体与快照
Project、Document、LineShape 使用 mobx-keystone 的 @model。要保存的字段用 tProp 声明,修改实体的方法标 @modelAction。对外改文档的方法在聚合根上:Project.addShape、Project.undo、Project.redo、Project.touch。
快照是实体在某一刻的普通对象。getSnapshot 取出它,applySnapshot 把实体恢复成那一份。Project.addShape 接受图形前,把 Document 的快照放进聚合自己的 past,undo 和 redo 再用 applySnapshot 换回来。past 和 future 在 onInit 里标成 observable,页面才能根据 canUndo、canRedo 重绘。它们不是 tProp,getSnapshot(project) 不包含撤销栈。
保存到本地库或提交给接口之前,仓储取出项目快照再写入。实体类仍然留在内存里给界面使用。编辑器 ViewModel 只持有当前的 project、store、工具和草稿。