Различные типы Иерархии инжекторов в Angular?

Иерархия инжекторов в Angular может иметь различные типы, которые определяются их организацией и связями между ними. Давайте рассмотрим основные типы иерархий инжекторов.

  1. Иерархия инжекторов на основе компонентов: Это самый распространенный тип иерархии инжекторов в Angular. Каждый компонент имеет свой собственный инжектор, который является потомком инжектора его родительского компонента. Это позволяет компонентам получать зависимости от своего инжектора или от инжекторов родительских компонентов. При этом инжекторы родительских компонентов являются общими для всех их дочерних компонентов.

  2. Иерархия инжекторов на основе модулей: Каждый модуль также имеет свой собственный инжектор, который является потомком инжектора его родительского модуля. Это означает, что провайдеры, определенные в родительском модуле, будут доступны для инъекции в компоненты и сервисы, определенные в дочерних модулях. Таким образом, иерархия инжекторов на основе модулей позволяет нам организовывать инъекции зависимостей на уровне модулей.

  3. Иерархия инжекторов на основе приложения: Верхним уровнем иерархии инжекторов является инжектор приложения. Он является корневым инжектором для всего приложения. Все модули и компоненты находятся в иерархии инжекторов, начиная с инжектора приложения. Это означает, что провайдеры, определенные на уровне приложения, будут доступны для инъекции во всех модулях и компонентах приложения.

Вот пример, демонстрирующий использование иерархии инжекторов на основе компонентов:

import { Component, Injectable, Injector } from '@angular/core'

@Injectable()
class DataService {
	getData(): string {
		return 'Данные из DataService'
	}
}

@Component({
	selector: 'app-child',
	template: ` <p>{{ data }}</p> `,
	providers: [DataService]
})
class ChildComponent {
	constructor(private dataService: DataService) {}

	get data(): string {
		return this.dataService.getData()
	}
}

@Component({
	selector: 'app-root',
	template: `
		<h1>Родительский компонент</h1>
		<app-child></app-child>
	`,
	providers: [DataService]
})
class ParentComponent {
	constructor(private injector: Injector) {
		const childInjector = Injector.create({
			parent: this.injector,
			providers: [{ provide: DataService, useValue: { getData: () => 'Данные из дочернего компонента' } }]
		})

		const childComponent = childInjector.get(ChildComponent)
		console.log(childComponent.data) // Выведет 'Данные из дочернего компонента'
	}
}

В этом примере у нас есть родительский компонент ParentComponent и дочерний компонент ChildComponent. Оба компонента используют одну и ту же службу DataService, но в дочернем компоненте мы переопределяем службу, предоставляя другую реализацию.

При создании дочернего инжектора с использованием Injector.create мы указываем родительский инжектор как parent: this.injector, что позволяет дочернему компоненту обратиться к провайдерам, определенным в родительском компоненте.

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