应用挂载与生命周期
本页解释业务应用怎样拥有 Canvas、启动 DirectSurface UI,以及为什么必须保存并释放 AppHost。先完成快速开始,再用本页建立稳定的应用壳层。
对象关系
宿主页面
└─ HTMLCanvasElement
└─ Application.mount(canvas)
└─ AppHost
└─ RenderWindow
└─ RenderPage / Workspace
└─ Layout + Widgets
- 宿主页面创建 Canvas,并决定它何时进入或离开 DOM。
Application负责把 runtime 挂到指定 Canvas。AppHost代表一次运行实例,持有 runtime、上下文与浮层服务。RenderWindow是 Render Tree 的应用根;页面或工作区是其子节点。
推荐启动器
把挂载和释放集中在一个模块中,避免路由切换、热更新或重复初始化时遗留监听器。
import { Application, MedicalCompactLightTheme, RenderPage, RenderText, RenderWindow, loadDirectSurfaceFonts, type AppHost,} from 'ds-ui' let host: AppHost | undefined export async function startApplication(selector = '#app'): Promise<AppHost> { host?.dispose() await loadDirectSurfaceFonts() const page = new RenderPage({ child: new RenderText('Application is ready') }) const mainWindow = new RenderWindow({ title: 'Business Application', chrome: 'none' }) mainWindow.setChildren([page]) host = Application.mount(selector).run(mainWindow, { theme: MedicalCompactLightTheme, }) return host} export function stopApplication(): void { host?.dispose() host = undefined}
生命周期规则
- Canvas 进入 DOM 且具有非零尺寸后再挂载。
- 同一个 Canvas 同一时间只运行一个
AppHost。 - 保存
.run()的返回值,不要只保留Application或根窗口。 - 页面卸载、路由切换、HMR 替换和测试结束时调用
host.dispose()。 - 重新挂载前先释放旧实例,避免重复键盘、指针和窗口监听。
dispose() 是应用实例的终点。普通页面内容切换应使用框架的页面、导航或工作区能力,不需要反复销毁整个 runtime。
应用级与页面级职责
| 层级 | 适合放置 | 不适合放置 |
|---|---|---|
| 宿主框架 | Canvas DOM、路由入口、登录跳转 | Canvas 内部布局与控件状态 |
| 应用壳层 | 主题、全局上下文、主窗口、全局命令 | 单个表单字段状态 |
| 页面/工作区 | 页面布局、查询条件、数据状态、局部命令 | 浏览器 DOM 生命周期 |
| 组件 | 展示、输入、选择、局部交互 | 应用启动和全局路由 |
什么时候使用多个 Canvas
普通业务系统优先使用一个应用 Canvas,在内部组合页面、弹窗和工作区。只有多个区域需要彼此独立的 runtime、主题和生命周期时,才创建多个 Canvas;每个 Canvas 都必须拥有独立的 AppHost 并单独释放。