我想通过useValue
提供程序声明一个字符串,供“可重用”模块中的组件使用。我希望我能够在几个顶级模块中覆盖具有不同值的相同“密钥”,并且将根据范围层次结构为可重用组件提供最近模块的值。
一个示例用例是CrudModule,它讲的是API基础知识(创建,列表等)。
为了保持代码DRY(没有大量继承),您可以通过依赖注入(例如“用户”,“团队”,“项目”)为路由v1/users
提供CRUD资源名称,{{1} },v1/teams
)。在此示例中,您可以将代码库组织到模块v1/projects
,UsersModule
,TeamsModule
,ProjectsModule
中。
这是一个Plunker展示我得到的与我的期望。这使用了Dogs vs Cats的一个更简单(人为)的例子,尝试从每个模块提供字符串CrudModule
vs "dog"
:
https://embed.plnkr.co/pNRpj6/
相比之下,如果您做同样的事情,但将提供商放在组件上,它会按预期工作:
https://embed.plnkr.co/BsgwmR/
对于我的应用程序设计,我不认为我可以通过将我的“多态提供程序”放在组件上来获得我需要的行为。最重要的是,我认为将这些放在我的模块上是一种更清洁,更好的设计。
我在第一个例子中做错了什么(模块上的提供者)? 我有什么遗漏这是预期的行为吗?
答案 0 :(得分:2)
添加到要导入根模块的模块的提供程序已添加到主进程器AppModuleInjector
当同时加载的两个导入模块列出具有相同令牌的提供者时,第二个模块的提供者“获胜”。
当Angular寻找为该令牌注入服务时,它会创建并传递由第二个提供者创建的实例。
每个注入此服务的类都会获取第二个提供程序创建的实例。即使在第一个模块中声明的类也会获得由第二个提供者创建的实例。
如果模块A为令牌“X”提供服务并导入也为令牌“X”提供服务的模块B,则模块A的服务定义“获胜”。
根AppModule提供的服务优先于导入模块提供的服务。 AppModule总是赢。
有两种限制服务范围的选项:
1)如果您必须热切地加载模块而不是在组件animal
数组中提供providers
<强> Plunker Example 强>
2)如果可以的话,懒洋洋地加载模块。 Angular为延迟加载的模块提供了自己的子注入器。