Angular 学习笔记 (五) - 服务Service和依赖注入
参考官方文档:https://angular.cn/tutorial/toh-pt4
一.服务
组件不应该直接获取或保存数据,它们不应该了解是否在展示假数据。 它们应该聚焦于展示数据,而把数据访问的职责委托给某个服务。
Service的作用便可以减少数据在不同模块之间的耦合,简化代码。
创建Service指令:
ng generate service hero
Service的结构:
1 import { Injectable } from '@angular/core'; 2 3 @Injectable({ 4 providedIn: 'root', 5 }) 6 export class HeroService { 7 8 constructor() { } 9 10 }
这里 providedIn: 'root' 的可以将Service声名为App的根目录,适用于作为一个单例服务
二.依赖注入
服务导入了 Angular 的 Injectable
符号,并且给这个服务类添加了 @Injectable()
装饰器。 它把这个类标记为依赖注入系统的参与者之一。
@Injectable()
装饰器会接受该服务的元数据对象,就像 @Component()
对组件类的作用一样。
你必须先注册一个服务提供者,来让 Service
在依赖注入系统中可用,Angular 才能把它注入到 Component
中。所谓服务提供者就是某种可用来创建或交付一个服务的东西;在这里,它通过实例化 HeroService
类,来提供该服务。
为了确保 HeroService
可以提供该服务,就要使用注入器来注册它。注入器是一个对象,负责当应用要求获取它的实例时选择和注入该提供者。
一个依赖注入的示例:
Recipe数据模型:
1 import { Ingredient } from '../shared/ingredient.model'; 2 3 export class Recipe { 4 public name: string; 5 public description: string; 6 public imagePath: string; 7 public ingredients: Ingredient[]; 8 9 constructor(name: string, desc: string, imagePath: string, ingredients: Ingredient[]) { 10 this.name = name; 11 this.description = desc; 12 this.imagePath = imagePath; 13 this.ingredients = ingredients; 14 } 15 }
服务:
1 import { EventEmitter, Injectable } from '@angular/core'; 2 3 import { Recipe } from './recipe.model'; 4 import { Ingredient } from '../shared/ingredient.model'; 5 import { ShoppingListService } from '../shopping-list/shopping-list.service'; 6 7 @Injectable() 8 export class RecipeService { 9 recipeSelected = new EventEmitter<Recipe>(); 10 11 private recipes: Recipe[] = [ 12 new Recipe( 13 'Tasty Schnitzel', 14 'A super-tasty Schnitzel - just awesome!', 15 'https://upload.wikimedia.org/wikipedia/commons/7/72/Schnitzel.JPG', 16 [ 17 new Ingredient('Meat', 1), 18 new Ingredient('French Fries', 20) 19 ]), 20 new Recipe('Big Fat Burger', 21 'What else you need to say?', 22 'https://upload.wikimedia.org/wikipedia/commons/b/be/Burger_King_Angus_Bacon_%26_Cheese_Steak_Burger.jpg', 23 [ 24 new Ingredient('Buns', 2), 25 new Ingredient('Meat', 1) 26 ]) 27 ]; 28 29 constructor(private slService: ShoppingListService) {} 30 31 getRecipes() { 32 return this.recipes.slice(); 33 } 34 35 addIngredientsToShoppingList(ingredients: Ingredient[]) { 36 this.slService.addIngredients(ingredients); 37 } 38 }
这里 ShoppingListService 是另一个服务,服务中可以注入另一个服务
服务注入Component:
recipes.component.ts:
1 import { Component, OnInit } from '@angular/core'; 2 3 import { Recipe } from './recipe.model'; 4 import { RecipeService } from './recipe.service'; 5 6 @Component({ 7 selector: 'app-recipes', 8 templateUrl: './recipes.component.html', 9 styleUrls: ['./recipes.component.css'], 10 providers: [RecipeService] 11 }) 12 export class RecipesComponent implements OnInit { 13 selectedRecipe: Recipe; 14 15 constructor(private recipeService: RecipeService) { } 16 17 ngOnInit() { 18 this.recipeService.recipeSelected 19 .subscribe( 20 (recipe: Recipe) => { 21 this.selectedRecipe = recipe; 22 } 23 ); 24 } 25 }
三. 依赖注入的层级
Root注入器并不是Angular应用中唯一的注入器。Modules 和 Components也有自己的注入器。Angular应用的注入器遵循一个层级制度。
每当Angular组件在其构造函数中定义了Token时,注入器就会在已注册提供者池中搜索与该Token匹配的类型。如果没有匹配,它将在父组件的提供者上委托搜索,并不断向注册器树上级找寻,直到root注入器。如果提供者查找结束时没有匹配,它将返回
如果没有找到匹配项,Angular就会抛出异常。
注入器树:
当组件寻求依赖时:
1st pass: 组件会依次来搜寻父组件,如果找到依赖,则停止寻找并请求改实例,若没有找到,进入2nd pass
2nd pass: 组件依次搜寻其父Module直到root,如果找到依赖,则停止寻找并请求改实例,如果没有找到,则抛出error
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2020-04-08 用npm server和webpack进行web部署
2019-04-08 Springboot中的事件Event