← Назад к вопросам

Что такое Host декоратор?

1.7 Middle🔥 161 комментариев
#TypeScript

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Host декоратор в Angular?

Host декоратор (@Host) — это специальный декоратор в Angular, который используется в конструкторах классов директив или компонентов для ограничения области поиска зависимостей при внедрении через механизм инъекции зависимостей (DI). Его ключевая функция — указать Angular-инжектору, что поиск нужного сервиса, значения или другой зависимости должен производиться только в инжекторах текущего компонента и его родительских компонентов, но не дальше по дереву инжекторов, включая корневой модуль (NgModule).

Механизм работы и область поиска

По умолчанию, когда Angular выполняет инъекцию зависимости, он начинает поиск с инжектора текущего элемента (например, компонента или директивы) и затем последовательно идет вверх по дереву инжекторов:

  • Инжектор текущего компонента
  • Инжектор родительского компонента
  • ... и так далее, до корневого инжектора модуля.

@Host изменяет это поведение, устанавливая границу поиска. С его использованием поиск прекращается на уровне инжектора текущего хоста. Хостом (Host) в контексте директивы считается компонент, в шаблон которого эта директива применена. Для компонента его собственный инжектор также считается хостом.

import { Directive, Host, Optional } from '@angular/core';
import { SomeService } from './some.service';

@Directive({
  selector: '[appMyDirective]'
})
export class MyDirective {
  constructor(@Host() @Optional() private someService: SomeService) {
    // Angular будет искать SomeService только в инжекторах:
    // 1. Компонента, где применена эта директива (хост)
    // 2. Родительских компонентов этого хоста
    // Но НЕ в корневом инжекторе модуля, если сервис не найден выше.
  }
}

Практическое применение и примеры

Host декоратор наиболее полезен в следующих сценариях:

1. Создание директив, которые зависят от сервисов, определенных только в конкретном компоненте

Если директива должна использовать сервис, который предоставлен именно в компоненте-хозяине (например, через providers в декораторе @Component), и не должна "видеть" экземпляр этого сервиса из корневого уровня, то @Host гарантирует это.

// Компонент предоставляет сервис локально
@Component({
  selector: 'app-parent',
  template: `<div appMyDirective></div>`,
  providers: [LocalService] // Сервис доступен только в этом компоненте и его потомках
})
export class ParentComponent {}

// Директива, которая требует этот локальный сервис
@Directive({
  selector: '[appMyDirective]'
})
export class MyDirective {
  constructor(@Host() private localService: LocalService) {
    // Получает LocalService именно из ParentComponent
    // Если бы @Host не использовался, директива могла бы получить
    // экземпляр из корневого инжектора, если он там есть.
  }
}

2. Контроль за "пузырьковым" эффектом в иерархии инжекторов

Без @Host директива, примененная в глубоком дочернем компоненте, может случайно получить сервис из корневого уровня, минуя промежуточные компоненты. @Host позволяет создавать более строгие, изолированные контексты зависимостей.

3. Использование вместе с @Optional

Часто @Host комбинируют с @Optional, чтобы избежать ошибок, если зависимость не найдена в ограниченной области поиска. В таком случае значение будет null.

constructor(@Host() @Optional() private maybeService: MaybeService) {
  if (this.maybeService) {
    // Сервис найден в хосте или его родителях
  }
}

Отличие от других декораторов инжекции

  • Без декоратора: Поиск идет до корневого инжектора.
  • @Self(): Поиск только в инжекторе текущего компонента/директивы (еще более строго, чем @Host).
  • @SkipSelf(): Исключает инжектор текущего элемента и начинает поиск с родителя.
  • @Host(): Поиск в текущем хосте и его родителях, но не выше.

Важные нюансы

  1. Для компонентов: Когда @Host используется в конструкторе компонента, хостом считается сам этот компонент. Поэтому поиск будет ограничен инжектором этого компонента и его родителями.
  2. Для модулей (NgModule): @Host не имеет смысла, так как модуль не имеет "хоста" в иерархии компонентов.
  3. С viewProviders: @Host также учитывает viewProviders компонента (которые доступны только для самого компонента и его шаблона, но не для дочерних компонентов с providers).

Пример с viewProviders

@Component({
  selector: 'app-host-example',
  template: `<child-comp></child-comp>`,
  viewProviders: [ViewOnlyService]
})
export class HostExampleComponent {}

@Component({
  selector: 'child-comp',
  template: `<div></div>`
})
export class ChildComponent {
  // ViewOnlyService доступен здесь через @Host, если ChildComponent
  // является частью шаблона HostExampleComponent
  constructor(@Host() viewOnlyService: ViewOnlyService) {
    // Получит сервис, потому что ChildComponent находится в шаблоне хоста
  }
}

Таким образом, @Host — это мощный инструмент для точного контроля за областью видимости зависимостей в Angular, позволяющий создавать более предсказуемую и модульную архитектуру приложения, особенно при разработке сложных директив и компонентов с локальными контекстами сервисов.