首页 > 解决方案 > 指令和组件中本地提供者的优先级

问题描述

我认为指令的本地提供者是为其内容子项提供服务,例如:

//template in a module 
<table>
   <tr>
      <td>{{ item.price | myPipe }}</td>    
   </tr>
</table>

myPipe在其构造函数中具有依赖关系MyService

因此,如果我将指令定义为:

@Directive({
    selector: "[myAttr]", 
    providers: [MyService]
})
export class MyDirective { }

并将其应用为:

<table>
   <tr myAttr>
      <td>{{ item.price | myPipe }}</td>    
   </tr>
</table>

那么MyServiceinmyPipe的构造函数就可以解决了。

但是如果有一个组件也在MyService其本地提供者中定义并将其应用为:

<myComponent>
   <tr myAttr>
      <td>{{ item.price | myPipe }}</td>    
   </tr>
</myComponent>

既然两者都可以为 提供服务MyDirective,那么将选择哪一个,本地提供者 还是?MyComponentmyPipemyPipeMyDirectiveMyComponent

标签: angularangular-directive

解决方案


前提

Angular 中的每个组件都有自己的 Injector 上下文,用于为其自身及其组件树提供服务(或更一般地说,Injectables)。

简短的回答

管道似乎总是使用它们所在模板的组件的 Injector 上下文(经过我的经验测试,需要引用)。parentComponent因此,如果您有一个带有如下模板的组件(我们称之为它):

<myComponent>
   <tr myAttr>
      <td>{{ item.price | myPipe }}</td>    
   </tr>
</myComponent>

那么myPipe不会从任何一个myComponentmyAttr!因此,您的问题的直接答案不是

相反,它将获得声明组件(即)使用(提供parentComponent)的服务实例。

简短说明

就 HTML 结构而言,它确实似乎是和myPipe的子级。然而,就 Angular 的层次结构而言,它是它的子级,因此它在那里获得了它的服务提供者。此外,与组件不同,管道不受内容投影的影响(使用)。myComponentmyAttr myPipeparentComponent<ng-content>

还...

您对如何提供服务的理解似乎不太正确。以下是对您所做陈述的一些更正:

  1. “[I]如果我将指令定义为 (...) 并应用它 (...),则可以解析 myPipe 的构造函数中的 MyService” - 不正确,如我的回答所示。
  2. “如果有一个组件也在其本地提供程序中定义 MyService (...) MyDirective 和 MyComponent 都可以为 myPipe 提供服务” - 出于同样的原因,也不正确。

最后

组件的行为与管道不同。它们形成组件树,并且 Injector 上下文相应地发生变化。因此,如果代替myPipe你有一个yetAnotherComponent,它实际上会得到由提供的 MyServicemyComponent不是parentComponent.

终于终于

如果您的指令提供服务并且您将该指令应用于组件,则该组件将获得指令提供的服务!当然,除非它自己注册了提供者。


推荐阅读