#angular #circular-dependency
#угловатый #циклическая зависимость
Вопрос:
Есть ли лучший способ обойти циклическую зависимость, если компонент использует службу, а служба инициализирует компонент? что я здесь сделал, так это то, что, поскольку компонент инициализируется службой, я внедряю саму службу в компонент без использования внедрения угловых зависимостей.
Служба рабочего пространства
@Injectable()
export class WorkspaceService {
name = "John";
constructor(
private cfr: ComponentFactoryResolver,
private appRef: ApplicationRef,
private injector: Injector
) {
this.appendWorkspaceToBody();
}
private appendWorkspaceToBody(): void {
const workspaceRef = this.cfr
.resolveComponentFactory(WorkspaceComponent)
.create(this.injector);
workspaceRef.instance.workspaceService = this;
this.appRef.attachView(workspaceRef.hostView);
const domElem: HTMLElement = (workspaceRef.hostView as EmbeddedViewRef<any>)
.rootNodes[0] as HTMLElement;
document.body.appendChild(domElem);
}
}
Компонент рабочей области
@Component({
selector: "app-workspace",
template: "{{workspaceService.name}}"
})
export class WorkspaceComponent implements OnInit {
public workspaceService: WorkspaceService
ngOnInit() {}
}
Чтобы проверить код проблемы, перейдите в stackblitz
Комментарии:
1. Вместо того, чтобы импортировать класс внутри службы, почему вы не можете передать в качестве аргумента appendWorkspaceToBody ?
2. что это изменит, поскольку оно вызывается только из своего конструктора
3. Да, это избавит от ошибки циклической зависимости. И вы должны вызвать его из компонента, вместо того, чтобы вызывать внутреннюю службу
4. тем не менее я получаю предупреждение о сборке для циклической зависимости
5. Я пробовал в stackblitz, это работает fine:stackblitz.com/edit/angular-ivy-qeqimh?file=src/app/workspace /…
Ответ №1:
Лучшее решение, которое я нашел для этой проблемы, — написать отдельную службу для инициализации компонента, которая выполняется из модуля путем предоставления в APP_INITIALISER .
Модуль
// @dynamic
@NgModule({
imports: [BrowserModule, FormsModule],
declarations: [AppComponent, HelloComponent, WorkspaceComponent],
bootstrap: [AppComponent],
providers: [
WorkspaceService,
WorkspaceInitializeService,
{
provide: APP_INITIALIZER,
useFactory: (service: WorkspaceInitializeService) => () =>
service.appendWorkspaceToBody(),
multi: true,
deps: [WorkspaceInitializeService]
}
]
})
export class AppModule {}
Обслуживание
@Injectable()
export class WorkspaceService {
name = "John";
constructor() {
}
}
Служба инициализации
@Injectable()
export class WorkspaceInitializeService {
constructor(
private cfr: ComponentFactoryResolver,
private injector: Injector
) {}
appendWorkspaceToBody(): void {
const workspaceRef = this.cfr
.resolveComponentFactory(WorkspaceComponent)
.create(this.injector);
this.injector.get(ApplicationRef).attachView(workspaceRef.hostView);
const domElem: HTMLElement = (workspaceRef.hostView as EmbeddedViewRef<any>)
.rootNodes[0] as HTMLElement;
document.body.appendChild(domElem);
}
}
Чтобы проверить код решения, перейдите в stackblitz