Приоритет локальных провайдеров в директивах и компонентах

Я думаю, что локальный поставщик директивы должен предоставлять услуги для своих дочерних элементов, например:

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

тогда MyService в конструкторе myPipe может быть разрешено.

Но если есть компонент, также определите MyService в его локальных провайдерах и примените его как:

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

поскольку и MyDirective, и MyComponent могут предоставлять услуги для myPipe, так что myPipe выберет местный поставщик MyDirective или MyComponent?

Хороший вопрос по очень запутанной теме. См. мой ответ, который, надеюсь, освещает практические аспекты проблемы в вашем конкретном случае. К сожалению, подробное объяснение было бы очень сложно написать, и оно соответствовало бы собственной документации Angular, которую я рекомендую вам прочитать: angular.io/guide/… и angular.io/guide/hierarchical. -внедрение-зависимости. Кроме того, в случае подобных неопределенностей, один из лучших способов сделать это - попробовать различные сценарии, что я и сделал - вы можете точно увидеть, как все это работает.

Avius 02.01.2021 14:19
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
5
1
431
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

помещение

Каждый компонент в Angular получает свой собственный контекст инжектора, который используется для предоставления услуг (или, в более общем смысле, инъекций) себе и своему дереву компонентов.

Короткий ответ

Кажется, что каналы всегда используют контекст Injector компонента, в шаблоне которого они находятся (эмпирически проверено мной, ссылка необходима). Итак, если у вас есть компонент (назовем его parentComponent) с шаблоном, который выглядит так:

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

тогда myPipe не получит экземпляр службы ни от myComponent, ни от myAttr! Так что прямой ответ на ваш вопрос - ни то, ни другое!

Вместо этого он получит экземпляр службы, используемый (предоставленный) объявляющим компонентом (т. е. parentComponent).

Краткое объяснение

С точки зрения структуры HTML действительно кажется, что myPipe является потомком как myComponent, так и myAttr. Однако с точки зрения иерархии Angular myPipe является дочерним элементом parentComponent, поэтому он получает там своего поставщика услуг. Кроме того, на каналы, в отличие от компонентов, не влияет проекция контента (использование <ng-content>).

Также...

Похоже, ваше понимание того, как предоставляются услуги, не совсем верно. Вот некоторые исправления сделанных вами заявлений:

  1. «[I] если я определяю директиву как (...) и применяю ее (...), тогда MyService в конструкторе myPipe может быть разрешен» - неверно, как указано в моем ответе.
  2. «Если есть компонент, также определите MyService в своих локальных провайдерах (...), и MyDirective, и MyComponent могут предоставлять услугу для myPipe» - тоже неверно по той же причине.

Окончательно

Компоненты ведут себя иначе, чем трубы. Они формируют деревья компонентов, и соответственно изменяются контексты Injector. Таким образом, если вместо myPipe у вас есть yetAnotherComponent, он фактически получит MyService, предоставляемый myComponent, а не parentComponent.

Наконец наконец

Если ваша директива предоставляет Службу и вы применяете эту Директиву к Компоненту, этот Компонент получит Службу в соответствии с Директивой! Если, конечно, он сам не зарегистрировал провайдера.

Другие вопросы по теме