angular-di by analogjs/angular-skills
npx skills add https://github.com/analogjs/angular-skills --skill angular-di在 Angular v20+ 中使用 inject() 和提供者来配置和使用依赖注入。
优先使用 inject() 而非构造函数注入:
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { User } from './user.service';
@Component({
selector: 'app-user-list',
template: `...`,
})
export class UserList {
// 注入依赖项
private http = inject(HttpClient);
private userService = inject(User);
// 可立即使用
users = this.userService.getUsers();
}
import { Injectable, inject, signal } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root', // 根级别单例
})
export class User {
private http = inject(HttpClient);
private users = signal<User[]>([]);
readonly users$ = this.users.asReadonly();
async loadUsers() {
const users = await firstValueFrom(
this.http.get<User[]>('/api/users')
);
this.users.set(users);
}
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// 推荐方式:providedIn
@Injectable({
providedIn: 'root',
})
export class Auth {}
// 替代方式:在 app.config.ts 中
export const appConfig: ApplicationConfig = {
providers: [
Auth,
],
};
@Component({
selector: 'app-editor',
providers: [EditorState], // 每个组件的新实例
template: `...`,
})
export class Editor {
private editorState = inject(EditorState);
}
export const routes: Routes = [
{
path: 'admin',
providers: [Admin], // 在此路由树内共享
children: [
{ path: '', component: AdminDashboard },
{ path: 'users', component: AdminUsers },
],
},
];
import { InjectionToken } from '@angular/core';
// 简单值令牌
export const API_URL = new InjectionToken<string>('API_URL');
// 对象令牌
export interface AppConfig {
apiUrl: string;
features: {
darkMode: boolean;
analytics: boolean;
};
}
export const APP_CONFIG = new InjectionToken<AppConfig>('APP_CONFIG');
// 带工厂的令牌(自提供)
export const WINDOW = new InjectionToken<Window>('Window', {
providedIn: 'root',
factory: () => window,
});
export const LOCAL_STORAGE = new InjectionToken<Storage>('LocalStorage', {
providedIn: 'root',
factory: () => localStorage,
});
// app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
{ provide: API_URL, useValue: 'https://api.example.com' },
{
provide: APP_CONFIG,
useValue: {
apiUrl: 'https://api.example.com',
features: { darkMode: true, analytics: true },
},
},
],
};
@Injectable({ providedIn: 'root' })
export class Api {
private apiUrl = inject(API_URL);
private config = inject(APP_CONFIG);
private window = inject(WINDOW);
getBaseUrl(): string {
return this.apiUrl;
}
}
// 提供实现
{ provide: Logger, useClass: ConsoleLogger }
// 条件实现
{
provide: Logger,
useClass: environment.production
? ProductionLogger
: ConsoleLogger,
}
// 静态值
{ provide: API_URL, useValue: 'https://api.example.com' }
// 配置对象
{ provide: APP_CONFIG, useValue: { theme: 'dark', language: 'en' } }
// 带依赖项的工厂
{
provide: User,
useFactory: (http: HttpClient, config: AppConfig) => {
return new User(http, config.apiUrl);
},
deps: [HttpClient, APP_CONFIG],
}
// 异步工厂(不推荐 - 使用 provideAppInitializer)
{
provide: CONFIG,
useFactory: () => fetch('/config.json').then(r => r.json()),
}
// 现有提供者的别名
{ provide: AbstractLogger, useExisting: ConsoleLogger }
// 多个令牌指向同一实例
providers: [
ConsoleLogger,
{ provide: Logger, useExisting: ConsoleLogger },
{ provide: ErrorLogger, useExisting: ConsoleLogger },
]
@Component({...})
export class My {
// 如果未提供则返回 null
private analytics = inject(Analytics, { optional: true });
trackEvent(name: string) {
this.analytics?.track(name);
}
}
@Component({
providers: [Local],
})
export class Parent {
// 仅在此组件的注入器中查找
private local = inject(Local, { self: true });
}
@Component({...})
export class Child {
// 跳过此组件,在父级中查找
private parentService = inject(ParentSvc, { skipSelf: true });
// 仅查找到宿主组件
private hostService = inject(Host, { host: true });
}
为同一令牌收集多个值:
// 用于多个验证器的令牌
export const VALIDATORS = new InjectionToken<Validator[]>('Validators');
// 提供多个值
providers: [
{ provide: VALIDATORS, useClass: RequiredValidator, multi: true },
{ provide: VALIDATORS, useClass: EmailValidator, multi: true },
{ provide: VALIDATORS, useClass: MinLengthValidator, multi: true },
]
// 作为数组注入
@Injectable()
export class Validation {
private validators = inject(VALIDATORS); // Validator[]
validate(value: string): ValidationError[] {
return this.validators
.map(v => v.validate(value))
.filter(Boolean);
}
}
// 拦截器内部使用多重提供者
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(
withInterceptors([
authInterceptor,
loggingInterceptor,
errorInterceptor,
])
),
],
};
使用 provideAppInitializer 在应用启动前运行异步代码:
import { provideAppInitializer, inject } from '@angular/core';
export const appConfig: ApplicationConfig = {
providers: [
Config,
provideAppInitializer(() => {
const configService = inject(Config);
return configService.loadConfig();
}),
],
};
providers: [
provideAppInitializer(() => {
const config = inject(Config);
return config.load();
}),
provideAppInitializer(() => {
const auth = inject(Auth);
return auth.checkSession();
}),
]
以编程方式创建注入器:
import { createEnvironmentInjector, EnvironmentInjector, inject } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class Plugin {
private parentInjector = inject(EnvironmentInjector);
loadPlugin(providers: Provider[]): EnvironmentInjector {
return createEnvironmentInjector(providers, this.parentInjector);
}
}
在注入上下文中运行代码:
import { runInInjectionContext, EnvironmentInjector, inject } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class Utility {
private injector = inject(EnvironmentInjector);
executeWithDI<T>(fn: () => T): T {
return runInInjectionContext(this.injector, fn);
}
}
// 用法
utilityService.executeWithDI(() => {
const http = inject(HttpClient);
// 使用 http...
});
有关高级模式,请参阅 references/di-patterns.md。
每周安装量
2.3K
仓库
GitHub 星标数
494
首次出现
2026年1月24日
安全审计
安装于
github-copilot1.9K
gemini-cli1.8K
opencode1.8K
codex1.8K
amp1.6K
kimi-cli1.6K
Configure and use dependency injection in Angular v20+ with inject() and providers.
Prefer inject() over constructor injection:
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { User } from './user.service';
@Component({
selector: 'app-user-list',
template: `...`,
})
export class UserList {
// Inject dependencies
private http = inject(HttpClient);
private userService = inject(User);
// Can use immediately
users = this.userService.getUsers();
}
import { Injectable, inject, signal } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root', // Singleton at root level
})
export class User {
private http = inject(HttpClient);
private users = signal<User[]>([]);
readonly users$ = this.users.asReadonly();
async loadUsers() {
const users = await firstValueFrom(
this.http.get<User[]>('/api/users')
);
this.users.set(users);
}
}
// Recommended: providedIn
@Injectable({
providedIn: 'root',
})
export class Auth {}
// Alternative: in app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
Auth,
],
};
@Component({
selector: 'app-editor',
providers: [EditorState], // New instance for each component
template: `...`,
})
export class Editor {
private editorState = inject(EditorState);
}
export const routes: Routes = [
{
path: 'admin',
providers: [Admin], // Shared within this route tree
children: [
{ path: '', component: AdminDashboard },
{ path: 'users', component: AdminUsers },
],
},
];
import { InjectionToken } from '@angular/core';
// Simple value token
export const API_URL = new InjectionToken<string>('API_URL');
// Object token
export interface AppConfig {
apiUrl: string;
features: {
darkMode: boolean;
analytics: boolean;
};
}
export const APP_CONFIG = new InjectionToken<AppConfig>('APP_CONFIG');
// Token with factory (self-providing)
export const WINDOW = new InjectionToken<Window>('Window', {
providedIn: 'root',
factory: () => window,
});
export const LOCAL_STORAGE = new InjectionToken<Storage>('LocalStorage', {
providedIn: 'root',
factory: () => localStorage,
});
// app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
{ provide: API_URL, useValue: 'https://api.example.com' },
{
provide: APP_CONFIG,
useValue: {
apiUrl: 'https://api.example.com',
features: { darkMode: true, analytics: true },
},
},
],
};
@Injectable({ providedIn: 'root' })
export class Api {
private apiUrl = inject(API_URL);
private config = inject(APP_CONFIG);
private window = inject(WINDOW);
getBaseUrl(): string {
return this.apiUrl;
}
}
// Provide implementation
{ provide: Logger, useClass: ConsoleLogger }
// Conditional implementation
{
provide: Logger,
useClass: environment.production
? ProductionLogger
: ConsoleLogger,
}
// Static values
{ provide: API_URL, useValue: 'https://api.example.com' }
// Configuration objects
{ provide: APP_CONFIG, useValue: { theme: 'dark', language: 'en' } }
// Factory with dependencies
{
provide: User,
useFactory: (http: HttpClient, config: AppConfig) => {
return new User(http, config.apiUrl);
},
deps: [HttpClient, APP_CONFIG],
}
// Async factory (not recommended - use provideAppInitializer)
{
provide: CONFIG,
useFactory: () => fetch('/config.json').then(r => r.json()),
}
// Alias to existing provider
{ provide: AbstractLogger, useExisting: ConsoleLogger }
// Multiple tokens pointing to same instance
providers: [
ConsoleLogger,
{ provide: Logger, useExisting: ConsoleLogger },
{ provide: ErrorLogger, useExisting: ConsoleLogger },
]
@Component({...})
export class My {
// Returns null if not provided
private analytics = inject(Analytics, { optional: true });
trackEvent(name: string) {
this.analytics?.track(name);
}
}
@Component({
providers: [Local],
})
export class Parent {
// Only look in this component's injector
private local = inject(Local, { self: true });
}
@Component({...})
export class Child {
// Skip this component, look in parent
private parentService = inject(ParentSvc, { skipSelf: true });
// Only look up to host component
private hostService = inject(Host, { host: true });
}
Collect multiple values for same token:
// Token for multiple validators
export const VALIDATORS = new InjectionToken<Validator[]>('Validators');
// Provide multiple values
providers: [
{ provide: VALIDATORS, useClass: RequiredValidator, multi: true },
{ provide: VALIDATORS, useClass: EmailValidator, multi: true },
{ provide: VALIDATORS, useClass: MinLengthValidator, multi: true },
]
// Inject as array
@Injectable()
export class Validation {
private validators = inject(VALIDATORS); // Validator[]
validate(value: string): ValidationError[] {
return this.validators
.map(v => v.validate(value))
.filter(Boolean);
}
}
// Interceptors use multi providers internally
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(
withInterceptors([
authInterceptor,
loggingInterceptor,
errorInterceptor,
])
),
],
};
Run async code before app starts using provideAppInitializer:
import { provideAppInitializer, inject } from '@angular/core';
export const appConfig: ApplicationConfig = {
providers: [
Config,
provideAppInitializer(() => {
const configService = inject(Config);
return configService.loadConfig();
}),
],
};
providers: [
provideAppInitializer(() => {
const config = inject(Config);
return config.load();
}),
provideAppInitializer(() => {
const auth = inject(Auth);
return auth.checkSession();
}),
]
Create injectors programmatically:
import { createEnvironmentInjector, EnvironmentInjector, inject } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class Plugin {
private parentInjector = inject(EnvironmentInjector);
loadPlugin(providers: Provider[]): EnvironmentInjector {
return createEnvironmentInjector(providers, this.parentInjector);
}
}
Run code with injection context:
import { runInInjectionContext, EnvironmentInjector, inject } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class Utility {
private injector = inject(EnvironmentInjector);
executeWithDI<T>(fn: () => T): T {
return runInInjectionContext(this.injector, fn);
}
}
// Usage
utilityService.executeWithDI(() => {
const http = inject(HttpClient);
// Use http...
});
For advanced patterns, see references/di-patterns.md.
Weekly Installs
2.3K
Repository
GitHub Stars
494
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
github-copilot1.9K
gemini-cli1.8K
opencode1.8K
codex1.8K
amp1.6K
kimi-cli1.6K
99,500 周安装