文档 / 示例 / 源码命名不一致的坑
这一页专门收录 vjcad 的"两种 / 三种说法都对"的地方。开发时被绕进去 → 来这里翻一下。
vjcad 是高频迭代的产品,官方文档 / 官方在线示例 / 实际类型 偶有命名 / 签名差异。本文按"碰到的命名歧义"归档。
⚠️ 原则:以示例代码(
vjcad/example/...)能跑为准;文档作为"理解性参考"。
1. viewMode vs viewerMode
| 来源 | 写法 |
|---|---|
| 文档(部分页面) | viewerMode: true |
| 示例 / 类型 | viewMode: 'viewer' |
✅ 正解:
new MainView({ viewMode: 'viewer' }); // 'full' | 'viewer'(完整编辑器 | 只读查看器)
viewerMode 在源码、types.d.ts 与 vjcad@1.0.16 打包产物中都不存在,传了会被静默忽略(不报错也不生效);只能用 viewMode。
2. entity.type 值:'PLINE' vs 'LWPOLYLINE'
实体 type 字段为大写类型名,但 PolylineEnt 是最容易踩的坑:
| 类 | type 字段(当前版本) |
|---|---|
LineEnt |
'LINE' |
CircleEnt |
'CIRCLE' |
ArcEnt |
'ARC' |
PolylineEnt |
'PLINE' ⚠️ 不是 'LWPOLYLINE' |
TextEnt |
'TEXT' |
MTextEnt |
'MTEXT' |
HatchEnt |
'HATCH' |
InsertEnt |
'INSERT' |
'LWPOLYLINE' 的合法位置:EntityTypeFilter 过滤器词表(QuickSelect 相关 API 入参,与 POLYLINE 并列,types.d.ts 可查)与兼容判断代码——源码 PatternMatchService/BoundaryDetector/TableExtractUtils 等 6 处都有 type === 'PLINE' || 'LWPOLYLINE'(甚至 || 'POLYLINE')的双匹配,用于兼容 DWG 导入/旧版本数据。运行时新建的 PolylineEnt 恒为 'PLINE'(构造函数写死),你自己代码里的类型判断只写 'PLINE' 即可。
Engine.getEntitiesByType('LINE'); // ✅
Engine.getEntitiesByType('PLINE'); // ✅ 多段线用这个
Engine.getEntitiesByType('LWPOLYLINE');// ❌ 当前实体永远不匹配(除非读老存档)
Engine.getEntitiesByType('Line'); // ❌ 找不到(内部 === 精确匹配,只做了 toUpperCase)
Engine.getEntitiesByType('LineEnt'); // ❌
3. entity.id 是 string 还是 number?
不同子类 / 不同文档说法:
architecture.md:entity.id: stringapi-reference.md:entity.id: number
实际:vjcad 内部是数字递增 ID,但 跨网络传输 / 序列化时通常字符串化(与 handle 一致)。
✅ 安全做法:
String(entity.id) // 永远用字符串比较
String(otherEntity.id) === String(entity.id)
不要直接 === 比较,避免类型不一致。
4. entity.move(dx, dy) 还是 entity.move(from, to)
| 来源 | 用法 |
|---|---|
文档 edit/edit-commands.md |
entity.move(dx, dy) 相对位移 |
示例 edit/01move.js |
entity.move(fromPoint, toPoint) 绝对两点 |
✅ 以示例为准:
entity.move([0, 0], [100, 50]); // 从原点移到 (100, 50)
如果你看到文档说 move(dx, dy),那是历史接口,未必在最新版生效。
5. 坐标转换的多种入口
| 写法 | 说明 |
|---|---|
Engine.canvasToWcs(p) |
顶层静态快捷(小写开头) |
Engine.trans.CanvasToWcs(p) |
CoordinateTransform 实例方法(大写开头) |
Engine.pcanvas.trans.CanvasToWcs(p) |
同一条 CoordinateTransform 链路 |
⚠️ 注意大小写不对称:Engine 静态方法是 canvasToWcs(小写),CoordinateTransform 实例方法是 CanvasToWcs(大写,配套 WcsToCanvas/DcsToWcs/WcsToDcs…)。写错大小写就是 undefined is not a function。
// 推荐:顶层
const wcs = Engine.canvasToWcs(canvasPoint);
不要混用,否则代码看起来"工程师不理解"。
6. Reactor 注册的真实入口
EntityReactorManager 只提供 registerReactor(reactor: IEntityReactor, docId?) / unregisterReactor(reactorId, docId?)——没有 entity.setReactor(r) 也没有 register({owner,target,onChange}) 配置对象形态(老资料里的两种写法都不存在)。
✅ 正确姿势:自定义实体实现 IEntityReactor(getOwnerIds/updateFromOwners/...),Engine.reactorManager.registerReactor(myReactorEnt, docId)。详见 reactor/ireactor-interface.md。
7. Engine.lineTypeManager vs Engine.linetypeManager
驼峰拼写不一致:
- 文档:
Engine.linetypeManager - 类型定义(types.d.ts):
Engine.linetypeManager
1.0.16 的 types.d.ts 里只有 linetypeManager(小写 t)。统一用 linetypeManager,不要写 lineTypeManager。
8. Engine.zoomExtents() vs Engine.pcanvas.zoomExtents()
二者等价 —— Engine.zoomExtents 是顶层静态快捷,Engine.pcanvas(CanvasController)上的同名方法也直接可调。注意是 pcanvas 不是 view:MainView 上没有 zoomExtents。
Engine.zoomExtents(); // 推荐
Engine.pcanvas.zoomExtents(); // 等价
9. LineEnt(p1, p2) —— 位置参数是唯一构造形式
vjcad 实体构造函数全部是位置参数(首参几何、末参可选 color),没有 new LineEnt({ start, end }) 这类对象式签名:
new LineEnt([0, 0], [100, 0]); // ✅ 点参数支持 [x,y] 数组或 Point2D
new LineEnt({ start: [0,0] }); // ❌ 不存在——会得到 startPoint=NaN 的实体
示例代码中怎么写就怎么用,不要自创签名。
10. mapbounds 字符串 vs 数组
// ❌ 数组
mapbounds: [minX, minY, maxX, maxY]
// ✅ 字符串
mapbounds: 'minX,minY,maxX,maxY'
文档少数早期页面写成数组形式,实际 API 是字符串。
11. appendItems / prependItems 顺序
ContextMenuOpening 的两个数组:
events.on(CadEvents.ContextMenuOpening, args => {
args.prependItems.push(item); // 加到默认菜单的最前
args.appendItems.push(item); // 加到默认菜单的最后
});
注意 prependItems 是 数组顺序就是显示顺序(先 push 的更靠前)。不是 unshift 语义。
12. setLoops(HatchEnt 唯一正确 API)
hatch.setLoops(edges); // ✅ 当前包中唯一存在的边界 API
hatch.setBoundary(edges); // ❌ 不存在(d.ts/运行时均无)——老资料里的写法会直接 TypeError
13. lineType(唯一正确写法,linetypeName 不存在)
| 写法 | 用途 |
|---|---|
entity.lineType |
官方 get/set 属性——读返回线型名,写接受 CONTINUOUS/别名/自定义名(内部转大写匹配) |
entity.linetypeName |
❌ 不存在(d.ts/运行时均无),赋值只是挂了个无效字段 |
line.lineType = 'HIDDEN'; // ✅
14. EntityErasing 与 EntityErased
vjcad 的事件命名:
EntityErasing/EntityErased:枚举里有,但 vjcad@1.0.16 从不派发(订阅永不触发)- 实际派发的是批量版
EntitiesErasing(可cancel,或往args.excludeEntities里放部分实体)/EntitiesErased
被某些社区文章误写成 EntityRemoving / EntityDeleted,请以 vjcad 类型 / 示例为准。
15. 总体策略
| 来源 | 可信度 | 用法 |
|---|---|---|
vjcad/example/*.js |
⭐⭐⭐⭐⭐ | 第一优先级 |
| TypeScript 类型 | ⭐⭐⭐⭐ | 接口 / 字段 |
文档 (vjcad/doc/) |
⭐⭐⭐ | 概念解释 |
| 网上零散文章 | ⭐ | 仅参考思路 |
红旗
- 当文档与示例冲突时,信示例
- 看到驼峰大小写不一致时,任选一种贯彻整个项目
- 看到"参数顺序" / "签名"歧义时,先
Object.getOwnPropertyNames(EntityClass.prototype)看真实方法 - 不要为"接口看起来更好看"而自创不存在的签名 —— 类型擦除后只剩字符串,编译器不会救你
- 老文档可能有效但不是"最佳实践",新功能(如 viewMode、reactorManager)始终用新 API
参考(官方文档 MCP)
- 本页内容来自实际写本 skill 时遇到的歧义对照,相关文档与示例在每条小节内已标注:
vjcad/doc/guide/architecture.md、vjcad/doc/command/api-reference.md、vjcad/doc/edit/edit-commands.md、vjcad/doc/ui/dialogs.md、vjcad/doc/event/event-types.md等 - 示例对照:
vjcad/example/basic/04viewerremote.js、vjcad/example/edit/01move.js、vjcad/example/entity/dimension/09associative.js等