【问题标题】:precedence of local providers in directives and components指令和组件中本地提供者的优先级
【发布时间】:2020-12-25 23:31:51
【问题描述】:

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

//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会选择哪一个,MyDirectiveMyComponent的本地提供者?

【问题讨论】:

  • 关于一个非常令人困惑的话题的好问题。请参阅我的回答,希望能在您的具体案例中突出问题的实际方面。遗憾的是,很难编写深入的解释,并且与 Angular 自己的文档相当,我鼓励您阅读:angular.io/guide/…angular.io/guide/hierarchical-dependency-injection。此外,如果有类似的不确定性,最好的办法之一是尝试不同的场景,这就是我所做的 - 你可以确切地看到它是如何工作的。

标签: angular angular-directive


【解决方案1】:

前提

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

简答

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

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

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

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

简短说明

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

还有……

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

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

终于

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

终于来了

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-08
    • 2023-03-14
    • 1970-01-01
    • 2013-08-05
    • 1970-01-01
    • 2012-06-21
    • 2016-07-20
    • 1970-01-01
    相关资源
    最近更新 更多