SKILL.md
只读
名称
angular-di
描述
使用 inject()、注入令牌和提供者配置在 Angular v20+ 中实现依赖注入。适用于服务架构、在不同层级提供依赖、创建可注入令牌以及管理单例与作用域服务。在服务创建、配置提供者、使用注入令牌或理解 DI 层级时触发。
Angular 依赖注入
使用 inject() 和提供者在 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);
}
}
提供者作用域
根级(单例)
// 推荐: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;
}
}
提供者类型
useClass
// 提供实现
{ provide: Logger, useClass: ConsoleLogger }
// 条件实现
{
provide: Logger,
useClass: environment.production
? ProductionLogger
: ConsoleLogger,
}
useValue
// 静态值
{ provide: API_URL, useValue: 'https://api.example.com' }
// 配置对象
{ provide: APP_CONFIG, useValue: { theme: 'dark', language: 'en' } }
useFactory
// 带依赖的工厂
{
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()),
}
useExisting
// 现有提供者的别名
{ 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);
}
}
Self、SkipSelf、Host
@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);
}
}
HTTP 拦截器(多提供者)
// 拦截器内部使用多提供者
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);
}
}
runInInjectionContext
在注入上下文中运行代码:
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。






