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

查看:17
本文介绍了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

根据文档:

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

我真的很苦恼如何让一个 3rd 方服务(我的 AppModuleimports 数组中的一个模块使用的服务)可用于延迟加载路线.我无法控制这个 3rd-party 模块,因此我不能从该模块的 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;dr:如何使来自第 3 方模块的服务成为我的延迟加载组件可用的单例?

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

这是一个演示问题的plunker(用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.

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

Here’s the new plunk - http://plnkr.co/edit/YDyJYu?p=preview

经过进一步审查,我在文档中发现了这一点:

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 ]
    };
  }
}

Plunk 更新并完全正常工作.(抱歉,更新了同一个)-> 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天全站免登陆