本地提供者在指令和组件中的优先级

precedence of local providers in directives and components

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

//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>

那么myPipe的构造函数中的MyService就可以解析了

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

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

因为 MyDirectiveMyComponent 都可以为 myPipe 提供服务,所以 myPipe 选择哪一个,MyDirective 的本地提供者或MyComponent?

前提

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

简答

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

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

那么 myPipe 而不是 myComponentmyAttr 获取服务实例!所以你问题的直接答案是 neither!

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

简短说明

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

还有...

看来您对服务提供方式的理解不太正确。以下是对您所做陈述的一些更正:

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

终于

组件的行为与管道不同。它们形成组件树并且注入器上下文相应地改变。因此,如果您使用 yetAnotherComponent 代替 myPipe,它 实际上会获得 myComponent 提供的 MyService,而不是 parentComponent ].

终于终于

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