Angular 服务和组件放置指南 | AI生成和翻译

Home 2026.03

问题:在 Angular (latest/v21) 中,如果一个组件有 standalone: false,其相关的 service 应该声明在 importsdeclarations 中,还是两者都有?

回答

这是一个关于 Angular 的 NgModule 系统中的两个不同、独立的关注点的问题。您需要清楚地区分以下两点:

  1. 组件本身(具有 standalone: false
  2. 组件使用的 service

这两者在 @NgModule 中进入完全不同的数组


规则总结

要注册的事物 @NgModule 中的位置
具有 standalone: false 的 component / directive / pipe declarations
service(或任何 provider) providers
在模板中要使用的 standalone component / NgModule / pipe imports

详细解释

1. 具有 standalone: false 的组件 → 放入 declarations

@NgModule 元数据的 declarations 属性声明属于该 NgModule 的 components、directives 和 pipes。组件必须标记为 standalone: false,才能在 NgModule 中声明。

@Component({
  selector: 'my-comp',
  standalone: false,
  template: `...`
})
export class MyComponent {}

@NgModule({
  declarations: [MyComponent], // ✅ 组件放入此处
})
export class MyModule {}

2. service → 放入 providers不是 importsdeclarations

当组件或 service 请求依赖时,Angular 的依赖注入系统会查找可以提供该依赖的 provider。Services 在 @NgModuleproviders 数组中注册。

@NgModule({
  declarations: [MyComponent],
  providers: [MyService], // ✅ service 放入此处
})
export class MyModule {}

3. 最佳实践:在 service 本身上使用 providedIn: 'root'

在现代 Angular 中,最推荐的方法是完全避免将 service 放入任何模块的 providers 数组中。相反,使用 providedIn: 'root' 来装饰 service:

@Injectable({
  providedIn: 'root' // ✅ 自动在所有地方可用
})
export class MyService {}

@Injectable 装饰器中使用 providedIn: 'root' 可以处理大多数常见用例,使 service 全局可用,而无需手动添加到任何 providers 数组。


4. 那么 imports 是做什么用的?

@NgModule 中的 imports 仅用于引入其他 NgModules 或 standalone components/directives/pipes,以便它们的导出声明在您的模板中可用。

@NgModule({
  imports: [CommonModule, RouterModule], // ✅ 其他模块 / standalone components
  declarations: [MyComponent],          // ✅ 非 standalone components/pipes/directives
  providers: [MyService],               // ✅ services / providers
})
export class MyModule {}

完整示例

// my.service.ts
@Injectable({ providedIn: 'root' })
export class MyService {}

// my.component.ts
@Component({
  selector: 'my-comp',
  standalone: false,
  template: `<p></p>`
})
export class MyComponent {
  constructor(private svc: MyService) {} // 通过 DI 注入
}

// my.module.ts
@NgModule({
  declarations: [MyComponent], // 组件在此声明
  imports: [CommonModule],     // 其他模块在此导入
  // MyService 不需要在此处,因为使用了 providedIn: 'root'
})
export class MyModule {}

最终答案

参考资料


Back Donate