首页 > 解决方案 > Angular 6 循环依赖逻辑解决方案

问题描述

我有逻辑问题。我需要将在服务中导入并在我需要该服务的组件中并行的组件。以下错误: Circular dependency: dist\services\modal.service.js -> dist\components\modal\modal.component.js -> dist\services\modal.service.js 这是解决这种情况的最佳方法。我最好的解决方案是使用第三个服务,它会以某种方式注入这两个文件。在服务中包含组件的原因是在其他组件中使用它。

服务.ts

import { ComponentFactoryResolver, EmbeddedViewRef, ApplicationRef, ComponentRef, Injectable, Injector
} from '@angular/core';
import { ModalComponent } from '../components/modal/modal.component';


@Injectable({
    providedIn: 'root'
})
export class ModalService {
    constructor(
        private componentFactoryResolver: ComponentFactoryResolver,
        private appRef: ApplicationRef,
        private injector: Injector
    ){}
    private data = {};
    private last;
    open(component: any, obj:any = {}) {
        if(!obj.id) obj.id = new Date().getTime();

        // Create a component reference from the component 
        const componentRef = this.componentFactoryResolver
          .resolveComponentFactory(component)
          .create(this.injector);
        // Attach component to the appRef so that it's inside the ng component tree
        this.appRef.attachView(componentRef.hostView)    
        // Get DOM element from component
        const contentElem = (componentRef.hostView as EmbeddedViewRef<any>)
          .rootNodes[0] as HTMLElement;
        // Create a component reference from the component 
        let componentRefer = this.componentFactoryResolver
          .resolveComponentFactory(ModalComponent)
          .create(this.injector);
        // Attach component to the appRef so that it's inside the ng component tree
        this.appRef.attachView(componentRefer.hostView);
        // Get DOM element from component
        const domElem = (componentRefer.hostView as EmbeddedViewRef<any>)
          .rootNodes[0] as HTMLElement;
        // Append DOM element to the body
        document.body.appendChild(domElem);
        // Append DcontentElemOM element to the body
        domElem.querySelector("#modalHoster").appendChild(contentElem);
        // Wait some time and remove it from the component tree and from the DOM

        this.data[obj.id]={
            componentRefer: componentRefer,
            appRef: this.appRef
        }
        this.last=obj;
        return obj.id;
    }
    pull(){
        return this.last;
    }
    close(id){
        this.data[id].appRef.detachView(this.data[id].componentRefer.hostView);
    }

}

组件.ts

import { Component, OnInit } from '@angular/core';
import { ModalService } from '../../services/modal.service';

@Component({
    selector: 'modal',
    templateUrl: './modal.component.html',
    styleUrls: ['./modal.component.scss']
})
export class ModalComponent implements OnInit {
    close(){
        this.mod.close(this.id);
    }
    constructor(private mod: ModalService){}
    ngOnInit() {
        let obj=this.mod.pull();
        for(let key in obj){
            this[key]=obj[key];
        }
    }
}

可能是我的逻辑错了,这就是我要问的。这两个服务和组件在模块内部,而不是应用程序。App 仅使用服务,组件不可访问。服务需要一段 html/css/ts 代码作为应用程序提供的一段 html/css/ts 代码的容器。

标签: angular

解决方案


您的逻辑在这里并没有真正错误,但您可以轻松避免循环依赖。

您肯定需要服务中的组件来创建新实例。但是,您实际上并不需要模态中的服务。

您可以做的是在您的模态中添加一个可观察的主题。当您实例化您的模式时,您在服务中订阅此主题以从容器中删除对话框。

这是一个简单的代码示例:)

在您的模态组件中:

private modalClose: Subject<any> = new Subject(); 

onModalClose(): Observable<any> {
    return this.modalClose.asObservable();
}

close() { // Will be generally called from the UI (close button for example)
   this.modalClose.next();
   this.modalClose.complete();
}

在您的服务中:

componentRefer.instance.onModalClose().subscribe( () => {
  // Here you close your modal :D
});

了解更多信息 :

在这里你可以找到我自己的“模态/对话框”。

https://github.com/xrobert35/asi-ngtools/tree/master/src/components/asi-dialog

要实例化一个对话框,您必须使用该服务。该服务管理一个可以有“许多”对话框的“容器”。使用相同的技术,我没有循环依赖。

在这里您可以找到该组件的工作示例:https ://ng-tools.asi.fr/views/showroom/asi-ngtools/components/asi-dialog


推荐阅读