为何在Angular模板中需浅拷贝Konva.Group子元素数组?
Angular 17 + Konva 图像编辑器子元素渲染问题解析
实现场景与代码
我用Angular 17结合Konva开发图像编辑器,为追踪和操作舞台对象,搭建了一个通过BehaviorSubject<Konva.Group>共享对象的Service,以及一个订阅该组、生成子元素列表的组件。
Service代码
export class StackService { private stack: BehaviorSubject<Konva.Group>; public stack$: Observable<Konva.Group>; constructor(){ let root = new Konva.Group({draggable: true}); this.stack = new BehaviorSubject(root); this.stack$ = this.stack.asObservable(); } }
组件TS代码
[...] this.stackService.stack$.subscribe((stack: Konva.Group) => { this.stack = stack; }); [...]
组件模板
<div *ngFor="let node of stack.getChildren()"> {{node.attrs.name}} </div>
遇到的问题
假设stack中已添加若干Konva.Shapes,但在组件订阅回调里执行console.log(this.stack.getChildren())时,控制台显示数组能看到7个元素,但length属性为0;模板里用*ngFor遍历stack.getChildren()也完全没有节点显示。
临时解决方法
在接收stack时,将子元素数组浅拷贝一份:
this.stackService.stack$.subscribe((stack: Konva.Group) => { this.stack = stack; this.nodes = stack.getChildren().slice(); });
之后模板改用拷贝后的nodes数组,就能正常显示所有节点名称。
疑问与最终根源
一开始疑惑为何必须浅拷贝才能正常渲染,后来找到问题本质:在舞台组件接收stack时,没有直接将整个stack组添加到舞台,而是把stack的所有子元素单独加到了舞台上——Konva的元素不能同时属于两个父容器,这会导致子元素从stack组中被移除,stack的子元素数组也就变成空的了。
内容的提问来源于stack exchange,提问作者Lapskaus
相关产品推荐
相关产品推荐

