绕过循环依赖

问题描述

如果组件使用服务并且服务初始化组件,是否有更好的方法解决循环依赖? 我这里所做的是,由于组件是由服务初始化的,所以我将服务本身注入到组件中,而没有使用角度依赖注入。

工作区服务

@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

解决方法

我为这个问题找到的更好的解决方案是为组件初始化编写一个单独的服务,该服务通过在 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