【问题标题】:Go around Circular dependency绕过循环依赖
【发布时间】:2021-02-07 08:18:45
【问题描述】:

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

工作区服务

@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

【问题讨论】:

  • 为什么不能在服务中导入类而不是作为参数传递给 appendWorkspaceToBody?
  • 它会发生什么变化,因为它只是从它的构造函数中调用的
  • 是的,它将摆脱循环依赖错误。而且你必须从组件调用它,而不是调用内部服务
  • 我仍然收到循环依赖的构建警告
  • 我在 stackblitz 中试过了,效果很好:stackblitz.com/edit/angular-ivy-qeqimh?file=src/app/workspace/…

标签: angular circular-dependency


【解决方案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

【讨论】:

    猜你喜欢
    • 2010-09-12
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多