Add a scaffold script that replaces the bq prefix with the new project name.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
53
doc/基础知识/mobx是什么.md
Normal file
53
doc/基础知识/mobx是什么.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# mobx是什么
|
||||
|
||||
MobX 负责页面上会变化的状态。mobx-keystone 负责可以保存、比较和恢复的实体。页面组件只负责渲染,不存放业务状态。
|
||||
|
||||
## 目录
|
||||
|
||||
- [页面状态](#页面状态)
|
||||
- [ViewModel 的生命周期](#viewmodel-的生命周期)
|
||||
- [实体与快照](#实体与快照)
|
||||
|
||||
## 页面状态
|
||||
|
||||
ViewModel 里需要触发重渲染的字段标成 `observable`,修改这些字段的方法标成 `action`。组件用 `mobx-react-lite` 的 `observer` 包起来,字段变化后才会重画。
|
||||
|
||||
`SecurityViewModel` 的 `errorMessage`、`isLoading` 就是页面状态。它们跟着这一次打开的登录页,所以这个类标 `@injectable('Transient')`。
|
||||
|
||||
普通字段不用 observable。不会显示在界面上的局部变量也不放进 ViewModel。
|
||||
|
||||
## ViewModel 的生命周期
|
||||
|
||||
ViewModel 继承 `PageViewModel`。页面不自己 `new`,而调用 `useViewModel`。
|
||||
|
||||
```ts
|
||||
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`、工具和草稿。
|
||||
Reference in New Issue
Block a user