Angular:了解DI如何在动态加载的组件中工作

欧金尼89

我遇到了注入动态加载的组件的服务的奇怪行为。考虑以下服务

@Injectable({
    providedIn: 'root'
})
export class SomeService {
    private random = Math.random() * 100;

    constructor() {
        console.log('random', this.random);
    }
}

该服务作为对两个组件的依赖关系而添加。第一个组件是延迟加载模块的一部分。而第二个是动态加载的。以下服务使用动态组件加载模块

export const COMPONENT_LIST = new InjectionToken<any>('COMPONENT_LIST');
export const COMPONENT_TYPE = new InjectionToken<any>('COMPONENT_TYPE');

@Injectable({
    providedIn: 'root'
})
export class LoaderService {
    constructor(
        private injector: Injector,
        private compiler: Compiler,
    ) { }

    getFactory<T>(componentId: string): Observable<ComponentFactory<T>> {
        // COMPONENT_LIST is passed through forRoot() from the module that declares first component
        const componentList = this.injector.get(COMPONENT_LIST); 
        const m = componentList.find(m => m.componentId === componentId);

        const promise: Promise<ComponentFactory<T>> = (!m) ? null :
            m.loadChildren
                .then((mod: any) => {
                    return this.compiler.compileModuleAsync(mod);
                })
                .then((mf: NgModuleFactory<any>) =>  {
                    const mr: NgModuleRef<any> = mf.create(this.injector);
                    const type: Type<T> = mr.injector.get<Type<T>>(COMPONENT_TYPE); // DYNAMIC_COMPONENT is provided in loaded module
                    return mr.componentFactoryResolver.resolveComponentFactory<T>(dynamicComponentType);
                });

        return from(promise);
    }
}

在同一模块中,我声明以下组件(放置动态加载的组件)和指令

@Component({
    selector: 'dynamic-wrapper',
    template: `<ng-container dynamicItem></ng-container>`
})
export class DynamicWrapperComponent implements AfterViewInit, OnDestroy {
    @Input() itemId: string;
    @Input() inputParameters: any;

    @ViewChild(DynamicItemDirective)
    private dynamicItem: DynamicItemDirective;

    private unsubscribe$: Subject<void> = new Subject();

    constructor(
        private loaderService: LoaderService
    ) { }

    ngAfterViewInit(): void {
        this.loaderService.getComponentFactory(this.itemId).subscribe((cf: ComponentFactory<any>) => {
            this.dynamicItem.addComponent(cf, this.inputParameters);
        });
    }
}
...
@Directive({
    selector: '[dynamicItem]'
})
export class DynamicItemDirective {

    constructor(protected viewContainerRef: ViewContainerRef) { }

    public addComponent(cf: ComponentFactory<any>, inputs: any): void {
        this.viewContainerRef.clear();
        const componentRef: ComponentRef<any> = this.viewContainerRef.createComponent(cf);
        Object.assign(componentRef.instance, inputs);
        // if I do not call detectChanges, ngOnInit in loaded component will not fire up
        componentRef.changeDetectorRef.detectChanges();
    }
}

SomeService 是在单独的模块中定义的,该模块同时导入具有第一个组件的延迟加载模块和动态加载模块。

初始化两个组件之后console.log('random', this.random),尽管providedIn: 'root'在装饰器中,我仍在控制台中看到带有两个不同数字的输出发生这种奇怪行为的原因是什么?

拉兹·罗嫩(Raz Ronen)

延迟加载的模块不会providedIn: 'root'像预期的那样做出反应仅当导入服务的模块没有延迟加载时,此选项才会将服务推送到AppModule(根模块)。

为什么会看到不同的随机数?

因为其中SomeService定义的模块启动了两次!(可以将console.log放在此模块的构造函数中)-因此该服务被启动了两次(我在我的项目延迟加载平台中自己遇到了这个问题)。

为什么包含的惰性模块SomeService启动两次?

loadChildrenmoduleFactory.create(this.injector)不保留延迟加载的模块的缓存。他们启动一个模块,并将其喷油器作为叶子连接到输入喷油器。

如果包含的模块SomeService是从创建的moduleFactory.create-您可以添加缓存层以返回缓存的已启动的延迟加载模块。

例如:

private lazyLoadedModulesCache: Map<Type<any>, NgModuleRef<any>>;

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在Angular的ts文件中销毁动态加载的组件?

来自分类Dev

如何在reactjs中动态加载组件?

来自分类Dev

如何在Angular中的另一个动态加载的组件内渲染组件?

来自分类Dev

如何在 angular 中使用动态加载的模块组件中的现有组件

来自分类Dev

如何在模板中按名称动态加载余烬组件?

来自分类Dev

在Angular2中动态加载组件

来自分类Dev

在Angular2中动态加载组件

来自分类Dev

如何在Angular 8中捕获动态渲染组件的输出?

来自分类Dev

如何在Angular / HTML中动态加载验证错误

来自分类Dev

如何在Angular 9中通过变量加载动态模块?

来自分类Dev

了解嵌套组件绑定如何在KnockoutJS上工作

来自分类Dev

了解BufferedReader如何在Java中工作

来自分类Dev

加载在angular2 final中动态创建的动态组件

来自分类Dev

动态加载组件 Angular 2

来自分类Dev

在CQ5 / AEM中,组件的项目加载路径如何在后台工作?

来自分类Dev

如何在动态组件周围包装Angular组件

来自分类Dev

如何在Angular的子组件内部动态创建组件?

来自分类Dev

如何在Svelte中动态渲染组件?

来自分类Dev

如何在动态加载的组件中隔离css

来自分类Dev

如何动态加载Angular2根组件

来自分类Dev

动态加载组件后如何让 angular2 更新内容

来自分类Dev

在angular2中使用动态组件加载程序?

来自分类Dev

在Angular2 RC.5中动态加载组件

来自分类Dev

使用选择器在Angular 2中动态加载组件

来自分类Dev

在Angular2 RC.5中动态加载组件

来自分类Dev

在 angular-2 中动态创建延迟加载的组件

来自分类Dev

如何在python中动态加载模块

来自分类Dev

如何在EmberJS中动态加载路由?

来自分类Dev

了解如何在React组件中引用属性

Related 相关文章

热门标签

归档