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

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

2.0 Middle🔥 191 комментариев
#JavaScript Core

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

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

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

Что такое декоратор @SkipSelf()?

@SkipSelf() — это параметр декоратора @Optional(), используемый в Angular для управления механизмом внедрения зависимостей (DI — Dependency Injection). Он указывает инжектору Angular пропустить локальный инжектор текущего компонента или директивы и начать поиск зависимости на уровне родительского инжектора.

Основная цель и принцип работы

В Angular иерархия инжекторов повторяет иерархию компонентов. Когда компонент запрашивает зависимость, Angular по умолчанию ищет её в следующем порядке:

  1. Локальный инжектор текущего компонента (где были объявлены провайдеры в providers).
  2. Родительский инжектор, затем его родитель и так далее вверх по дереву компонентов.
  3. Корневой инжектор модуля.

@SkipSelf() изменяет этот алгоритм, заставляя DI игнорировать первый шаг и начинать поиск сразу с родительского инжектора.

Практический пример использования

Представим, что у нас есть сервис LogService, который предоставляется на уровне родительского компонента, но не на уровне дочернего. Если дочерний компонент попытается его инжектировать стандартным способом, возникнет ошибка, так как локальный провайдер отсутствует. @SkipSelf() в комбинации с @Optional() решает эту проблему.

// Родительский компонент предоставляет сервис
@Component({
  selector: 'app-parent',
  template: `<app-child></app-child>`,
  providers: [LogService] // Сервис предоставлен здесь
})
export class ParentComponent {}

// Дочерний компонент
@Component({
  selector: 'app-child',
  template: `...`
  // providers: [LogService] // Здесь сервис НЕ предоставлен
})
export class ChildComponent {
  constructor(
    // @SkipSelf() говорит Angular: "Не ищи LogService в моём собственном инжекторе,
    // начни поиск с инжектора родителя".
    // @Optional() предотвращает ошибку, если сервис в итоге не будет найден.
    @Optional() @SkipSelf() private logService: LogService
  ) {
    if (this.logService) {
      this.logService.info('Компонент создан');
    }
  }
}

// Сам сервис
@Injectable()
export class LogService {
  info(message: string) {
    console.log(`[INFO]: ${message}`);
  }
}

В этом примере LogService будет успешно найден в инжекторе ParentComponent. Без @SkipSelf() Angular попытался бы найти его в инжекторе ChildComponent, потерпел неудачу и выбросил бы ошибку NullInjectorError (если бы не @Optional()).

Ключевые сценарии применения

  • Избежание циклических зависимостей: Когда дочерний и родительский компоненты предоставляют один и тот же сервис, и дочернему нужно инжектировать именно родительскую реализацию.
  • Модификация родительских сервисов: Создание "декоратора" или "обёртки" вокруг родительского сервиса в дочернем компоненте.
  • Гибкое управление областью видимости (Scope): Явное указание, что зависимость должна быть получена из контекста родителя, что делает код более предсказуемым.

Важные комбинации и аналоги

  • @SkipSelf() + @Optional(): Стандартная практика для безопасного инжектирования опциональной зависимости из родительского контекста.
  • @Host(): Другой модификатор поиска, который ограничивает поиск зависимостью текущего хоста (компонента, директивы). @SkipSelf() и @Host() часто используются вместе для тонкого контроля.
  • @Self(): Антагонист @SkipSelf(). Он указывает Angular искать зависимость только в локальном инжекторе текущего компонента, игнорируя родительские.

Пример: Разрешение конфликта имён

// Родитель предоставляет конфиг
@Component({
  providers: [
    { provide: 'API_URL', useValue: 'https://parent-api.com' }
  ]
})
export class ParentComponent {}

@Component({
  providers: [
    // Дочерний компонент тоже предоставляет токен 'API_URL'!
    { provide: 'API_URL', useValue: 'https://child-api.local' }
  ]
})
export class ChildComponent {
  constructor(
    // Чтобы получить значение от родителя, а не своё собственное,
    // используем @SkipSelf().
    @SkipSelf() @Inject('API_URL') private parentApiUrl: string,
    // А это инжектирует локальное значение.
    @Inject('API_URL') private myApiUrl: string
  ) {
    console.log(parentApiUrl); // Выведет: 'https://parent-api.com'
    console.log(myApiUrl);     // Выведет: 'https://child-api.local'
  }
}

Итог

@SkipSelf() — это мощный инструмент для точного управления механизмом разрешения зависимостей в Angular. Он позволяет разработчику явно указать, что зависимость должна быть получена из контекста родительского элемента, а не из текущего. Это повышает контроль над областью видимости сервисов, помогает избегать конфликтов и реализовывать сложные паттерны, такие как декораторы или иерархические конфигурации. Использование вместе с @Optional() является рекомендуемой практикой для написания устойчивого к ошибкам кода.

Что такое SkipSelf декоратор? | PrepBro