Angular 中的服务层

发布: (2025年12月20日 GMT+8 15:05)
4 min read
原文: Dev.to

Source: Dev.to

根级服务:全局 MVP 🌍

当你使用 Angular CLI(ng generate service)生成服务时,默认代码如下:

@Injectable({
  providedIn: 'root'
})
export class UserService { }

Angular 会创建 唯一的实例 并在整个应用中共享它。
可以把它想象成酒店前台的接待员:所有组件都与同一个接待员对话,得到相同的信息。

常见使用场景

  • 认证服务 – 在所有组件之间共享登录状态
  • 配置服务 – 全局应用设置,且不会变化
  • HTTP/API 服务 – 与后端通信的单一入口
  • 状态管理 – 多个组件需要共享的数据

根级服务是大多数场景的首选,因为它们简单、高效,且避免了不必要的实例化。

组件级服务:本地化 🏠

如果一个服务只应由单个组件使用——或者每个组件实例都需要自己的副本——可以在组件层面提供它:

@Component({
  selector: 'app-shopping-cart',
  templateUrl: './shopping-cart.component.html',
  providers: [CartService]
})
export class ShoppingCartComponent { }

每当创建该组件时,Angular 会为该组件 新建一个实例CartService
类比:每个酒店房间都有专属的管家;101 房间有自己的管家,102 房间有另一位管家,它们之间不共享信息。

何时使用

  • 表单状态 – 每个表单组件保存自己的数据
  • 组件特定逻辑 – 必须防止泄漏到其他组件的数据
  • 多个实例 – 同一组件在页面上出现多次且需要独立行为

示例:在多个页面上展示的 ProductFilterComponent,每个实例都记住自己的过滤条件。

模块级服务:折中方案 ⚖️

如果你使用 Angular 模块(而不是独立组件),可以在模块层面提供服务:

@NgModule({
  declarations: [...],
  imports: [...],
  providers: [AuthGuardService]
})
export class AdminModule { }

急加载模块

当模块在应用启动时加载,服务的行为类似于整个应用的单例——等同于 providedIn: 'root'

懒加载模块

当模块以懒加载方式加载(例如通过路由),Angular 会为该模块创建 独立的注入器,从而为服务提供 新的实例,其作用域仅限于该懒加载特性。

const routes: Routes = [
  { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) }
];

在这种情况下,AdminService 只存在于懒加载的 admin 模块内部,模块卸载时也随之销毁。

应该使用哪种方式? 🤔

问题推荐作用域
服务是否需要在整个应用中使用?根级 ✅
服务是否只被单个组件使用?组件级 ✅
服务是否限定在需要懒加载的特性模块中?模块级 ✅

理解 Angular 依赖注入 层级——注入器如何沿组件树向上解析依赖——有助于你决定合适的作用域。

结论 💡

  • 根级:唯一实例,整个应用共享。
  • 组件级:每个组件拥有新实例。
  • 模块级:实例取决于急加载还是懒加载。

选择正确的层级可以让你的应用易于维护且性能良好;错误的选择则会让调试变得头疼。

Back to Blog

相关文章

阅读更多 »