我的问题场景如下,
我有一个带有大表格的页面(+100 个输入)。这些输入分为多个部分,这些部分被开发为不同的组件(用于重用目的)。所以页面的总体布局是这样的,
<div>
<form-section-a></form-section-a>
<form-section-b></form-section-b>
<form-section-c></form-section-c>
...
<form-section-z></form-section-z>
</div>
每个表单部分都需要一些时间来处理,因为大部分输入是材料选择框,并且需要从 REST API 加载必要的数据并进行处理。
在上面显示的布局中,angular 会尝试一次渲染所有表单部分,因此会增加每个部分的处理时间,这将导致浏览器冻结。
所以,我的计划是一个接一个地加载部分。有没有推荐的方法来实现这一目标?
我试图编写一个结构指令来一个接一个地加载组件。即使该指令有效,我也无法知道组件何时完成其内部处理工作(可能是 AfterViewInit 挂钩)。该指令看起来像这样,
<div tcSequentialRenderer>
<form-section-a *tcIfPreviousBlockLoaded></form-section-a>
<form-section-b *tcIfPreviousBlockLoaded></form-section-b>
<form-section-c *tcIfPreviousBlockLoaded></form-section-c>
...
<form-section-z *tcIfPreviousBlockLoaded></form-section-z>
</div>
.
@Directive({selector: '[tcSequentialRenderer]'})
export class SequentialRendererDirective implements AfterViewInit {
@ContentChildren(IfPreviousBlockLoadedDirective) directives: QueryList<IfPreviousBlockLoadedDirective>;
ngAfterViewInit() {
// start from first item
if (this.directives.length > 0) {
this.directives.toArray()[0].show();
}
let directivesArray = this.directives.toArray();
for (let i = 1; i < directivesArray.length; i++) {
directivesArray[i - 1].done.subscribe(status => {
if (status) {
directivesArray[i].show();
}
});
}
}
}
.
@Directive({selector: '[tcIfPreviousBlockLoaded]'})
export class IfPreviousBlockLoadedDirective {
private isShown = false;
public done: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor(
private tplref: TemplateRef<any>,
private vcref: ViewContainerRef
) { }
public show(): void {
if (!this.isShown) {
this.vcref.createEmbeddedView(this.tplref);
this.isShown = true;
}
}
}
如果我能以某种方式从IfPreviousBlockLoadedDirective
这个方法访问关联的组件,它将无缝地工作。
是否有任何建议可以解决此问题,或者是否有任何其他方法可以在不更改表单部分组件的情况下实现此目的?
注意:表单部分可以是任何角度组件。