Angular 2如何使单例服务可用于延迟加载的模块 [英] Angular 2 How to make singleton service available to lazy loaded modules

查看:91
本文介绍了Angular 2如何使单例服务可用于延迟加载的模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据我对Angular 2 rc5的理解,要使来自另一个模块(而非AppModule)的服务可以作为单例提供给每个组件,即使是那些延迟加载的组件,我们也不要 将服务包含在该其他模块的providers数组中.我们改为使用RouterModule.forRoot()导出并将结果导入AppModule

According to my understanding of Angular 2 rc5, to make a service from another module (not AppModule) available as a singleton to every component, even those lazy-loaded, we don't include the service in the providers array of that other module. We instead export it with RouterModule.forRoot() and import the result in AppModule

根据文档 a>:

SharedModule仅应在由以下人员导入时提供UserService: 根AppModule. SharedModule.forRoot方法可帮助我们满足此要求 挑战... SharedModule没有providers ...当我们添加时 将SharedModule导入AppModule,我们称为forRoot.在 这样做,AppModule获得了导出的类,并且 SharedModule在同一时间提供单例UserService提供程序 时间

The SharedModule should only provide the UserService when imported by the root AppModule. The SharedModule.forRoot method helps us meet this challenge...the SharedModule does not have providers...When we add the SharedModule to the imports of the AppModule, we call forRoot. In doing so, the AppModule gains the exported classes and the SharedModule delivers the singleton UserService provider at the same time

我真的在如何使第三方服务(我的AppModuleimports数组中的模块所使用的服务)可供延迟加载的路由使用.我无法控制此第三方模块,因此不能像从使用其中一项服务那样,仅从该模块的NgModule.providers数组中删除该服务并将其放置在RouterModule.forRoot()中.

I'm really struggling with how to make a 3rd-party service (a service used by a module in the imports array of my AppModule) available to lazy loaded routes. I have no control over this 3rd-party module, so I cannot just remove that service from the NgModule.providers array of that module and place it inside RouterModule.forRoot() as I would with one of my services.

特定服务是MdIconRegistry,它在Angular Material 2 alpha 7-3MdIconModuleproviders中.此服务用于注册svg图标,然后可以使用<md-icon svgIcon='iconName'>标签在页面上显示它们.所以:

The specific service is MdIconRegistry, which is in providers for the MdIconModule of Angular Material 2 alpha 7-3. This service is used to register svg icons that can then be displayed on the page with the <md-icon svgIcon='iconName'> tag. So:

  • 我在根AppModule
  • 中导入了MdIconModule
  • 我使用了相关服务在AppComponent
  • 中注册了svg图标
  • I imported MdIconModule in my root AppModule
  • I used the service in question to register svg icons in my AppComponent

该图标可见并且运行良好,但仅在启动时加载的模块中有效.延迟加载的模块无法看到这些图标,因此我怀疑Angular注入器未注入MdIconRegistry服务的同一实例.

The icon is visible and works well, but only in the modules that were loaded at launch. Lazy-loaded modules cannot see these icons, so I suspect that the Angular injector is not injecting the same instance of the MdIconRegistry service.

tl;博士:我如何才能使从第三方模块提供的服务成为我的延迟加载组件可以使用的单例服务?

tl;dr: How can I make the service from a 3rd-party module a singleton available to my lazy-loaded components?

这是演示此问题的插件(在typescript中编码).

PS:这刚引起GitHub上MdIconModule开发人员的注意.

PS: This just got the attention of the MdIconModule developer on github.

推荐答案

I do not think it has anything to do with the component being lazy-loaded.

LazyLoadedComponent不是AppModule的一部分–它是LazyModule的一部分.根据文档,一个组件只能是一个模块的一部分.如果您还尝试将LazyLoadedComponent添加到AppModule,则将收到错误消息.因此,LazyLoadedComponent甚至根本看不到MdIconModule.您可以通过在调试器中查看模板输出来确认这一点-它保持不变.

LazyLoadedComponent is not part of the AppModule – it is part of the LazyModule. According to the docs, a component can only be part of one module. If you try adding LazyLoadedComponent to AppModule also, you would get an error to that effect. So LazyLoadedComponent is not even seeing MdIconModule at all. You can confirm this by looking at the template output in the debugger – it is unchanged.

<md-icon svgIcon="play"></md-icon>

该解决方案似乎是将MdIconModule添加到LazyModule,虽然仅此不能解决问题,但确实会向输出添加错误.

The solution appears to be adding the MdIconModule to the LazyModule, and while this alone does not fix the problem, it does add an error to the output.

错误检索图标:错误:找不到名称为:play"的图标

Error retrieving icon: Error: Unable to find icon with the name ":play"

模板输出现在看起来像这样,所以我们知道它正在加载.

And the template output now looks like this, so we know it is loading.

<md-icon role="img" svgicon="play" ng-reflect-svg-icon="play" aria-label="play"></md-icon>

我添加了从LazyLoadedComponent到addSvgIconSet的调用,并且使它起作用了……因此,这证明了每个组件都有MdIconRegistry服务的实例–不是您想要的,但可能会为您指明正确的方向.

I added the call to addSvgIconSet from LazyLoadedComponent, and that got it working… so this proves there is an instance of the MdIconRegistry service per component – not what you want, but may point you in the right direction.

这是新的小家伙- http://plnkr.co/edit/YDyJYu?p=preview

经过进一步审查,我在 docs 中找到了此

After further review, I found this in the docs:

为什么在延迟加载的模块中提供的服务仅对该模块可见?

Why is a service provided in a lazy loaded module visible only to that module?

与启动时加载的模块的提供程序不同,延迟加载的模块的提供程序在模块范围内.

Unlike providers of the modules loaded at launch, providers of lazy loaded modules are module-scoped.

最终更新!这就是答案.没有为延迟加载的组件正确设置MdIconModule ...但是我们可以轻松创建自己的模块,并对其进行正确设置并使用它.

Final Update! Here is the answer. MdIconModule is not properly setup for lazy loaded components... but we can easily create our own module that IS properly set up and use that instead.

import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';

import { MdIcon } from '@angular2-material/icon';
import { MdIconRegistry } from '@angular2-material/icon';

@NgModule({
  imports: [HttpModule],
  exports: [MdIcon],
  declarations: [MdIcon]
})
export class MdIconModuleWithProviders {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: MdIconModuleWithProviders,
      providers: [ MdIconRegistry ]
    };
  }
}

插件已更新,并且可以正常工作. (抱歉,更新相同)-> http://plnkr.co/edit/YDyJYu?p=preview

Plunk updated and fully working. (sorry, updated the same one) -> http://plnkr.co/edit/YDyJYu?p=preview

一个人可能会提交一个拉取请求,以便Angular Material导出两种样式的模块.

One might submit a pull request such that Angular Material exports modules of both styles.

这篇关于Angular 2如何使单例服务可用于延迟加载的模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆