非常棒的问题 Amanda!💡
在 Angular 的依赖注入(DI)系统中,useClass, useValue, useExisting, useFactory 是用来告诉 Angular:
“当某个东西要被注入时,我希望你如何创建或获取它的实例。”
🔍 四种方式对比(+ 示例)
| 方式 | 用途 | 是否支持依赖注入 | 创建方式 |
|---|---|---|---|
useClass | 用某个类创建新实例(最常见) | ✅ 是 | new MyClass(...) |
useValue | 用现成的对象/值 | ❌ 否 | 直接使用这个值 |
useExisting | 复用已有的实例(别名) | ✅ 是 | 指向已有提供者 |
useFactory | 用函数返回实例(可以自定义复杂逻辑) | ✅ 是 | 调用函数并注入依赖 |
✅ 全部例子:以 LoggerService 为核心来说明
🔧 准备一个服务类
export class LoggerService {
log(msg: string) {
console.log('LoggerService: ' + msg);
}
}
1️⃣ useClass: 最常见,默认行为
providers: [
{ provide: LoggerService, useClass: LoggerService }
]
➡️ 相当于:每次注入 LoggerService,都用这个类构造一个新实例。
2️⃣ useValue: 使用已有的对象或值
export const simpleLogger = {
log: (msg: string) => console.log('SimpleLogger: ' + msg)
};
providers: [
{ provide: LoggerService, useValue: simpleLogger }
]
➡️ LoggerService 实际上就是这个 JS 对象,不是类实例。
🧠 适合 mock 数据、常量、配置对象。
3️⃣ useExisting: 指向另一个已提供的 token
export class BetterLoggerService {
log(msg: string) {
console.log('BetterLogger: ' + msg);
}
}
providers: [
BetterLoggerService,
{ provide: LoggerService, useExisting: BetterLoggerService }
]
➡️ LoggerService 和 BetterLoggerService 实际上是同一个实例。
🧠 用于别名、兼容旧代码。
4️⃣ useFactory: 工厂函数创建,适合带逻辑、参数的情况
export function loggerFactory(): LoggerService {
const logger = new LoggerService();
logger.log('Logger created by factory!');
return logger;
}
providers: [
{ provide: LoggerService, useFactory: loggerFactory }
]
➡️ 每次注入 LoggerService,调用 loggerFactory() 返回实例。
➕ 示例:带依赖的 useFactory
export function advancedLoggerFactory(http: HttpClient): LoggerService {
const logger = new LoggerService();
logger.log('Logger created with HTTP capability');
return logger;
}
providers: [
{
provide: LoggerService,
useFactory: advancedLoggerFactory,
deps: [HttpClient]
}
]
🧠 总结口诀
| 场景 | 用法 |
|---|---|
| 类创建实例(最常见) | useClass |
| 已有对象、常量、Mock | useValue |
| 想让多个 Token 共享实例 | useExisting |
| 要带逻辑、传参、复杂创建过程 | useFactory |