本地提供者在指令和组件中的优先级
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>
因为 MyDirective
和 MyComponent
都可以为 myPipe
提供服务,所以 myPipe
选择哪一个,MyDirective
的本地提供者或MyComponent
?
前提
Angular 中的每个组件都有自己的 Injector 上下文,用于为自身及其组件树提供服务(或更一般地说,Injectables)。
简答
管道似乎总是使用它们所在模板的组件的注入器上下文(经过我的经验测试,需要引用)。因此,如果您有一个组件(我们称它为 parentComponent
),其模板如下所示:
<myComponent>
<tr myAttr>
<td>{{ item.price | myPipe }}</td>
</tr>
</myComponent>
那么 myPipe
将 而不是 从 myComponent
或 myAttr
获取服务实例!所以你问题的直接答案是 neither!
相反,它将获取声明组件(即parentComponent
)使用的服务实例(提供)。
简短说明
就 HTML 结构而言,myPipe
确实是 myComponent
和 myAttr
的子代。然而,在 Angular 的层次结构方面 myPipe
是 parentComponent
的子级,因此它在那里获得其服务提供者。此外,与组件不同,管道不受内容投影的影响(使用 <ng-content>
)。
还有...
看来您对服务提供方式的理解不太正确。以下是对您所做陈述的一些更正:
- "[I]如果我将指令定义为 (...) 并应用它 (...),则可以解析 myPipe 的构造函数中的 MyService" - 不正确,如我的回答所示。
- “如果有组件还在其本地提供程序中定义 MyService (...) MyDirective 和 MyComponent 都可以为 myPipe 提供服务”- 也不正确,原因相同。
终于
组件的行为与管道不同。它们形成组件树并且注入器上下文相应地改变。因此,如果您使用 yetAnotherComponent
代替 myPipe
,它 会 实际上会获得 myComponent
提供的 MyService,而不是 parentComponent
].
终于终于
如果您的指令提供服务并且您将该指令应用于组件,则该组件将获得指令提供的服务!当然,除非它自己注册了提供商。
我认为指令的本地提供程序是为其内容子项提供服务,例如:
//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>
因为 MyDirective
和 MyComponent
都可以为 myPipe
提供服务,所以 myPipe
选择哪一个,MyDirective
的本地提供者或MyComponent
?
前提
Angular 中的每个组件都有自己的 Injector 上下文,用于为自身及其组件树提供服务(或更一般地说,Injectables)。
简答
管道似乎总是使用它们所在模板的组件的注入器上下文(经过我的经验测试,需要引用)。因此,如果您有一个组件(我们称它为 parentComponent
),其模板如下所示:
<myComponent>
<tr myAttr>
<td>{{ item.price | myPipe }}</td>
</tr>
</myComponent>
那么 myPipe
将 而不是 从 myComponent
或 myAttr
获取服务实例!所以你问题的直接答案是 neither!
相反,它将获取声明组件(即parentComponent
)使用的服务实例(提供)。
简短说明
就 HTML 结构而言,myPipe
确实是 myComponent
和 myAttr
的子代。然而,在 Angular 的层次结构方面 myPipe
是 parentComponent
的子级,因此它在那里获得其服务提供者。此外,与组件不同,管道不受内容投影的影响(使用 <ng-content>
)。
还有...
看来您对服务提供方式的理解不太正确。以下是对您所做陈述的一些更正:
- "[I]如果我将指令定义为 (...) 并应用它 (...),则可以解析 myPipe 的构造函数中的 MyService" - 不正确,如我的回答所示。
- “如果有组件还在其本地提供程序中定义 MyService (...) MyDirective 和 MyComponent 都可以为 myPipe 提供服务”- 也不正确,原因相同。
终于
组件的行为与管道不同。它们形成组件树并且注入器上下文相应地改变。因此,如果您使用 yetAnotherComponent
代替 myPipe
,它 会 实际上会获得 myComponent
提供的 MyService,而不是 parentComponent
].
终于终于
如果您的指令提供服务并且您将该指令应用于组件,则该组件将获得指令提供的服务!当然,除非它自己注册了提供商。