唯杰地图 logo唯杰地图
VJMAP
EN

onload-lifecycle

vjcad/references/setup/onload-lifecycle.md 4.8 KB92 行
原文

本文回答:await cadView.onLoad() 是异步初始化的同步点;它在 PixiJS 画布创建、WASM 模块加载、字体加载、插件系统初始化、URL 参数处理全部就绪后才 resolve,之前禁止使用 Engine。

一、onLoad() 在等什么

引自 vjcad/doc/guide/quick-start.md:

onLoad() 返回一个 Promise,在以下初始化完成后 resolve:

  • PixiJS 画布创建
  • WASM 模块加载
  • 字体加载
  • 插件系统初始化
  • URL 参数处理(自动打开图纸、激活侧边栏面板等)

支持的 URL 参数包括 vcad_mapid(图纸ID)、vcad_panel(激活面板)等。

二、最小用法

const { MainView, initCadContainer, Engine, LineEnt, message } = vjcad;

const cadView = new MainView({
  appname: '唯杰CAD',
  version: 'v1.0.0',
  serviceUrl: env.serviceUrl,
  accessToken: env.accessToken,
});

initCadContainer('map', cadView);

// 必须 await
await cadView.onLoad();

// 此时 Engine 才可用
message.info('初始化完成,开始绑定事件和创建实体...');

const line = new LineEnt([0, 0], [100, 100]);
line.setDefaults();
Engine.addEntities(line);
Engine.zoomExtents();

MCP 参考:vjcad/example/basic/02onload.js。

三、为什么必须 await

onLoad 前访问 Engine.* 的实际行为(并非"全是 undefined"):

getter onLoad 前实际返回 风险
Engine.pcanvas null(view?.pcanvas ?? null) Engine.addEntities 内部 if (!pcanvas) return ——静默丢弃不抛错,实体凭空消失
Engine.editor / Engine.view / Engine.trans undefined / null 访问属性抛 TypeError
Engine.currentDoc / currentSpace / undoManager 懒创建的孤儿 CadDocument(activeDocument getter 自动 new),不是 undefined 最阴险:调用"能跑"但写进的是脱离视图的文档,onLoad 后真文档替换,数据丢失
Engine.eventManager 真单例(CadEventManager.getInstance(),与 onLoad 后同一个) 无——onLoad 前注册监听有效(旧文档"不会注册到真正单例"的说法有误;resetInstance 是 @internal 仅供测试,MainView 初始化不调它)
  • WASM 模块还没加载就调 Engine.editor.executerWithOp('LINE') 会失败。
  • 字体没加载完就创建 TextEnt,会显示错位或空文字。
  • 插件系统未就绪时调用 PluginManager.getInstance().loadByName(...) 会丢调用。

四、URL 参数自动打开图纸

onLoad 内部会处理 URL 上的 vcad_mapid / vcad_panel / vcad_version / vcad_branch / vcad_patch / vcad_readonly / vcad_tile / vcad_workspace 等(具体支持详见 vjcad/doc/file/file-operations.md 的 "URL 参数自动打开图纸")。如果你只需要查看图纸,配合 viewer-mode 即可省掉自己的 DrawingManagerService.openDrawing 调用。

五、销毁与重建(cadView.destroy())

vjcad 按"一次一个视图"设计:文档、撤销、命令表、事件管理器都是 Engine 上的全局静态状态。弹框 / 路由反复打开 CAD 时,关闭前必须 await cadView.destroy(),再次打开重新 new MainView + initCadContainer + await onLoad():

// 关闭
await cadView.destroy();   // 依次:卸载全部插件 → 释放 Engine.docs 中全部文档 → 销毁画布 → 清理 Engine 静态缓存 → cad-view 移出 DOM
cadView = null;            // 等价写法:await Engine.destroyViewer();

// 再次打开
cadView = new MainView({ /* ... */ });
initCadContainer(hostElement, cadView);   // 也可直接传容器元素
await cadView.onLoad();

不 destroy 就重建:Engine 的静态缓存仍指向已卸载的旧画布,第二次打开"初始化成功但不显示图纸"。同一页面不要同时保留多个 MainView(见 trouble/init-pitfalls §7)。

MCP 参考:vjcad/example/basic/07destroyviewer.js。

反例

  • cadView.onLoad() 没 await,紧接着调 Engine.addEntities(...) —— 不报错但实体根本没进图(pcanvas 为 null 时静默 return),比报错更难排查。
  • 在 onLoad 之前监听 eventManager 事件不会注册到真正的单例上 —— 此说法有误:eventManager getter 就是 CadEventManager.getInstance() 全局单例,onLoad 前注册有效。
  • 写成 await initCadContainer(...).onLoad():initCadContainer 返回的是 HTMLElement(容器元素,同步返回非 Promise),上面没有 onLoad;onLoad 是 MainView 实例方法。

参考(官方文档 MCP)

  • 文档:vjcad/doc/guide/quick-start.md、vjcad/doc/file/file-operations.md
  • 示例:vjcad/example/basic/02onload.js、vjcad/example/basic/01init.js