我试图订阅组件销毁事件。组件A动态创建组件B并将其插入组件为DOM之外。我想订阅destory事件,以便我可以删除创建的组件。
ComponentRef有一个方便的onDestroy方法,但我找不到一种方法来获取对代表组件A(通常是按照创建)的ComponentRef的引用。
我可以传入一个发射器,在组件A中实现onDestroy并在销毁时向它发出并对此作出反应,但这似乎非常繁琐且烦人,不得不一遍又一遍地做。
编辑:
我最终从另一个角度来看这个。我编写了一个组件来充当中介,使用自己的ViewContainerRef来清理东西。
import {
ApplicationRef, Component, ContentChild, ContentChildren, EmbeddedViewRef, OnDestroy,
QueryList,
TemplateRef, ViewChild,
ViewContainerRef, ViewEncapsulation
} from '@angular/core';
@Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ModalComponent implements OnDestroy {
@ContentChild('title') title: TemplateRef<any>;
@ContentChild('body') body: TemplateRef<any>;
@ContentChildren('button') buttons: QueryList<TemplateRef<any>>;
@ViewChild(TemplateRef) modaltemplate;
views: EmbeddedViewRef<any>[] = [];
constructor(private appRef: ApplicationRef, private vcRef: ViewContainerRef) {
}
show (context) {
setTimeout(() => {
const modalView = this.vcRef.createEmbeddedView(this.modaltemplate);
const modalTitleView = this.vcRef.createEmbeddedView(this.title, {$implicit: context});
const modalBodyView = this.vcRef.createEmbeddedView(this.body, {$implicit: context});
const modalElement = modalView.rootNodes[0];
this.views.push(modalView, modalTitleView, modalBodyView);
const titleElement = modalElement.querySelector('.modal-card-title');
const bodyElement = modalElement.querySelector('.modal-card-body');
const buttonsElement = modalElement.querySelector('.buttons');
modalTitleView.rootNodes.forEach(c => {
titleElement.appendChild(c);
});
modalBodyView.rootNodes.forEach(c => {
bodyElement.appendChild(c);
});
this.buttons.forEach(b => {
const buttonView = this.vcRef.createEmbeddedView(b, {$implicit: context});
buttonView.rootNodes.forEach(n => {
if (n.classList.contains('cancel')) {
n.addEventListener('click', () => this.hide());
}
buttonsElement.appendChild(n);
});
this.views.push(buttonView);
});
document.body.appendChild(modalElement);
}, 0);
}
hide () {
this.views.splice(0, this.views.length)
.forEach(v => {
v.destroy();
});
}
ngOnDestroy(): void {
this.views.splice(0, this.views.length)
.forEach(v => {
v.destroy();
});
}
}
用法:
<app-modal #deleteModal>
<ng-template #title let-data>Are you sure you want to unassign {{data.profile.name}} from {{data.place.name}} {{data.place.shortDescription}}?</ng-template>
<ng-template #body>Don't worry, you can always reassign them back later.</ng-template>
<ng-template #button let-data><button class="button is-info" (click)="data.removeStaff(data.place, data.profile)">Unassign Staff</button></ng-template>
<ng-template #button><button class="button cancel">Cancel</button></ng-template>
</app-modal>