구성 요소 순환 참조 문제 및 현재 해결 방법
18524 단어 Angular
어떤 시기에 일어나는가
특정 Dialog를 표시하고 싶습니다. Dialog의 Component 중 Acomponent, Bcomponent의 표시를 동적으로 변화시키고 싶다.
@Component({
})
export class Acomponent implements OnInit {
constructor(private dialog: Dialog) {
}
open() {
/// AcomponentでDialogを経由してBcomponentを呼び出す
this.dialog.open(Bcomponent)
}
}
@Component({
})
export class Bcomponent implements OnInit {
constructor(private dialog: Dialog) {
}
open() {
/// BcomponentでDialogを経由してAcomponentを呼び出す
this.dialog.open(Acomponent)
}
}
이 때 compile시에 다음과 같은 warning이 표시된다.
WARNING in Circular dependency detected:
a-component.ts -> dialog.ts -> b-component.ts
WARNING in Circular dependency detected:
b-component.ts -> dialog.ts -> a-component.ts
해결 방법
도해하면
DialogNameEnum
export enum DialogName {
A,
B
}
ParentComponent
<app-a-component *ngIf="componentList[0].active" (toDialog)="openDialog($event)"></app-a-component>
<app-b-component *ngIf="componentList[1].active" (toDialog)="openDialog($event)"></app-b-component>
interface DialogList {
name: DialogName;
component: any;
active: boolean;
}
export interface ParentDialogData {
dialogName: DialogName;
}
@Component({
selector: 'app--parent-dialog',
templateUrl: './parent-dialog.component.html',
styleUrls: ['./parent-dialog.component.scss'],
})
export class ParentDialogComponent implements OnInit, OnDestroy {
loading$: Observable<boolean>;
private dialogCloseSubscription: Subscription;
componentList: Array<DialogList> = [
{
active: true,
name: DialogName.A,
component: AComponent,
},
{
active: false,
name: DialogName.B,
component: BComponent,
},
];
constructor(
@Inject(MAT_DIALOG_DATA) public data: ParentDialogData,
public readonly matDialogRef: MatDialogRef<ParentDialogComponent>,
private dialogService: DialogCloseService,
) {
this.query.selectLoading();
}
ngOnInit() {
this.openDialog(this.data.dialogName);
this.dialogCloseSubscription = this.dialogService.sharedDataSource$.subscribe((msg) => {
if (msg === 'close') {
this.matDialogRef.close();
}
});
}
openDialog(name: DialogName) {
this.componentList.forEach((c) => (c.active = false));
this.componentList.find((c) => c.name === name).active = true;
}
close() {
this.matDialogRef.close();
}
ngOnDestroy(): void {
this.dialogCloseSubscription.unsubscribe();
}
}
Acomponent
@Component({
selector: 'app-a',
templateUrl: './a.component.html',
styleUrls: ['./a.component.scss'],
changeDetection: ChangeDetectionStrategy.Default,
})
export class AComponent implements OnInit {
@Output() toDialog: EventEmitter<DialogName> = new EventEmitter();
constructor(
private readonly dialog: DialogCloseService,
) {}
ngOnInit() {
}
toBDialog() {
this.toDialog.emit(DialogName.B);
}
closeDialog() {
this.dialog.close();
}
Bcomponent
@Component({
selector: 'app-b',
templateUrl: './b.component.html',
styleUrls: ['./b.component.scss'],
changeDetection: ChangeDetectionStrategy.Default,
})
export class BComponent implements OnInit {
@Output() toDialog: EventEmitter<DialogName> = new EventEmitter();
constructor(
private readonly dialog: DialogCloseService,
) {}
ngOnInit() {
}
toADialog() {
this.toDialog.emit(DialogName.A);
}
closeDialog() {
this.dialog.close();
}
CloseService
Subject를 통해 close 감지
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class DialogCloseService {
constructor() {}
private sharedDataSource = new Subject<string>();
public sharedDataSource$ = this.sharedDataSource.asObservable();
close() {
this.sharedDataSource.next('close');
}
}
요약
단점으로서는 전환하는 component가 늘어날 때마다 ParentComponent를 수정하지 않으면 안되는 곳.
ngComponentOutlet등을 구사해 스마트하게 하기 위한 안 기다리고 있습니다.
Reference
이 문제에 관하여(구성 요소 순환 참조 문제 및 현재 해결 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/ryuseikurata/items/43ce06cc34c3cbcb6c77텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)