Dependency Injection (DI) — это паттерн проектирования, который позволяет разделять создание зависимостей и их использование. В контексте Stencil, DI применяется для управления сервисами и компонентами, что упрощает тестирование и повышает модульность приложений.
Stencil поддерживает встроенный механизм сервисов,
который позволяет регистрировать объекты как зависимости и внедрять их в
компоненты. Любой сервис в Stencil — это класс с аннотацией
@Injectable().
Пример создания сервиса:
import { Injectable } from '@stencil/core';
@Injectable()
export class LoggerService {
log(message: string) {
console.log('[Logger]:', message);
}
}
@Injectable() помечает класс как сервис, который может
быть внедрён в компоненты.В Stencil сервисы регистрируются через контейнер зависимостей, который создается автоматически для каждого проекта. При регистрации можно задавать область действия:
Пример регистрации:
import { Config, Injectable } from '@stencil/core';
@Injectable({
scope: 'singleton'
})
export class ApiService {
fetchData(url: string) {
return fetch(url).then(res => res.json());
}
}
scope: 'singleton' гарантирует, что в приложении будет
использоваться один объект ApiService.
Для внедрения зависимости используется декоратор
@Inject():
import { Component, h, Inject } from '@stencil/core';
import { LoggerService } from './logger-service';
@Component({
tag: 'app-logger',
styleUrl: 'app-logger.css',
shadow: true
})
export class AppLogger {
@Inject() private logger: LoggerService;
componentWillLoad() {
this.logger.log('Компонент загружается');
}
render() {
return <div>Проверка логирования</div>;
}
}
@Inject() автоматически передаёт экземпляр
зарегистрированного сервиса.Stencil поддерживает внедрение нескольких зависимостей одновременно:
import { Component, h, Inject } from '@stencil/core';
import { LoggerService } from './logger-service';
import { ApiService } from './api-service';
@Component({
tag: 'app-dashboard',
shadow: true
})
export class AppDashboard {
@Inject() private logger: LoggerService;
@Inject() private api: ApiService;
async componentWillLoad() {
this.logger.log('Загрузка данных');
const data = await this.api.fetchData('/api/data');
this.logger.log('Данные загружены: ' + JSON.stringify(data));
}
render() {
return <div>Дашборд загружен</div>;
}
}
DI позволяет легко подменять реальные сервисы мок-объектами. Например, для тестирования:
class MockApiService {
fetchData() {
return Promise.resolve([{ id: 1, name: 'Test' }]);
}
}
// В компоненте теста можно внедрить MockApiService вместо реального ApiService
Это устраняет необходимость в сетевых запросах при unit-тестах и делает код предсказуемым.
Stencil предоставляет мощный, но простой механизм Dependency Injection, который обеспечивает чистую архитектуру и упрощает поддержку масштабных приложений.