一、服务的创建和使用
1.服务的创建
服务可以简单理解为共享(公用)的模块,可供多个组件使用,就好像是vue
中的vuex
。例如在Angular
项目中,我们使用以下命令创建一个animal
服务
ng generate service services/animal
# 简写命令
ng g s services/animal
生成的animal.service.ts
文件,如下
// anmial.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AnimalService {
constructor() { }
}
2.服务的使用
更新animal.service.ts
文件,添加data
数据
// anmial.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AnimalService {
data: Array<{name: string, id: number}> = [
{ name: '孔雀', id: 1001 },
{ name: '老虎', id: 1002 },
{ name: '鸭子', id: 1003 },
{ name: '梅花鹿', id: 1004 },
{ name: '河马', id: 1005 },
{ name: '狮子', id: 1006 },
{ name: '棕熊', id: 1007 },
];
constructor() { }
}
创建一个组件,并在该组件中使用animal
服务
- 导入服务
- 在构造函数中声明服务的类型
- 使用服务
import { Component, OnInit } from '@angular/core';
import { AnimalService } from '../../services/animal.service'; // 第一步,导入该服务,主要用于类型定义
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.less']
})
export class HomeComponent implements OnInit {
// 第二步,在构造函数声明该服务
constructor(private animalService: AnimalService) { }
ngOnInit(): void {
// 第三步,使用服务
console.log('获取动物数据:', this.animalService.data);
}
}
二、服务使用的注意事项
1. providedIn
我们注意到修饰器Injectable
中的配置项providedIn: 'root'
providedIn: 'root'
相当于在根模块导入这个服务,如过去掉providedIn: 'root'
,则需要在app.module.ts
文件中的providers
导入该服务(使用时也可在对应的模块/组件中的providers
导入该服务),否则使用该服务时会报错。
// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AnimalService } from './services/animal.service';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [AnimalService], // 导入服务
bootstrap: [AppComponent]
})
export class AppModule { }
如果我们希望只在特定模块中使用该服务,比如,在Animal
模块使用Animal
服务
// animal.module.ts
import { NgModule } from '@angular/core';
import { AnimalComponent } from './animal.component';
import { AnimalService } from './services/animal.service';
@NgModule({
declarations: [
AnimalComponent
],
imports: [],
providers: [AnimalService], // 导入服务
bootstrap: []
})
export class AnimalModule { }
2. Injectable修饰器
若我们去掉整个Injectable
修饰器,然后在app.module.ts
或相关模块/组件中的providers
配置该服务,使用时也是正常的。
// anmial.service.ts
export class AnimalService {
data: Array<{name: string, id: number}> = [
{ name: '孔雀', id: 1001 },
{ name: '老虎', id: 1002 },
{ name: '鸭子', id: 1003 },
{ name: '梅花鹿', id: 1004 },
{ name: '河马', id: 1005 },
{ name: '狮子', id: 1006 },
{ name: '棕熊', id: 1007 },
];
constructor() { }
}
但是当我们在服务的构造器添加参数并声明参数类型时,会报错
// anmial.service.ts
import { HttpClient } from '@angular/common/http';
export class AnimalService {
data: Array<{name: string, id: number}> = [
{ name: '孔雀', id: 1001 },
{ name: '老虎', id: 1002 },
{ name: '鸭子', id: 1003 },
{ name: '梅花鹿', id: 1004 },
{ name: '河马', id: 1005 },
{ name: '狮子', id: 1006 },
{ name: '棕熊', id: 1007 },
];
constructor(private http: HttpClient) { } // 由于没有Injectable修饰器会报错
}
此时我们添加Injectable
修饰器就恢复正常了,所以我们可以简单理解Injectable
修饰器的其中一个作用就是用于服务构造函数中声明参数类型的。在日常开发中,建议服务都统一保留Injectable
修饰器,以免出现意想不到的错误。
// anmial.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
@Injectable()
export class AnimalService {
data: Array<{name: string, id: number}> = [
{ name: '孔雀', id: 1001 },
{ name: '老虎', id: 1002 },
{ name: '鸭子', id: 1003 },
{ name: '梅花鹿', id: 1004 },
{ name: '河马', id: 1005 },
{ name: '狮子', id: 1006 },
{ name: '棕熊', id: 1007 },
];
constructor(private http: HttpClient) { } // 有Injectable修饰器,不会报错
}
3. 在构造函数进行服务类型声明
为什么在app.module.ts
或相关模块/组件中的providers
配置完服务,在使用时还需要在构造函数进行类型声明?
这是因为我们配置时只是告诉angular
我们注入了该服务,在使用时需要构造注入该服务依赖的对象类型。