Angular中的服务
文章目录
前言
Angular 服务是 Angular 应用程序中用于封装可重用逻辑的类。服务在应用程序的多个组件之间共享数据和功能,而不依赖于应用程序的UI。服务可以用于诸如数据处理、与后端通信、用户身份验证等任务。
Angular 把数据与业务进行了抽离,希望我们能够单一的专注于数据的处理和数据的展示。所以就建立了服务的概念。这里的服务不是后台中的服务,本质是函数的封装。封装很多方法,对数据进行处理和返回。
以下是 Angular 服务的一些关键点:
- 依赖注入: Angular服务通过依赖注入(DI)系统在应用程序中使用。这意味着组件或其他服务可以请求服务的实例,而不需要知道如何创建这些实例。
- 单例模式: 默认情况下,Angular 服务是单例的,这意味着每个服务类在应用程序中只有一个实例。
- 惰性初始化: 服务只在第一次请求时创建,之后每次请求都会返回同一个实例。
- 服务定义: 使用 @Injectable 装饰器定义服务,并通过 providedIn 属性或在模块中手动添加来指定服务的作用域。
- 服务使用: 组件或其他服务可以通过构造函数注入来使用服务。
一、创建服务
使用命令创建
bash
ng g service 服务名
在这里我在services目录下创建一个data服务
bash
ng g service services/data
这个组件就创建好了。
二、使用服务
使用命令创建data组件
bash
ng g component components/data
在服务中写一些功能
csharp
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'// 这里的'root'意味着服务将在整个应用中可用
})
export class DataService {
constructor() { }
// 示例数据
private data: any[] = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
{ id: 4, name: 'Item 4' },
{ id: 5, name: 'Item 5' },
{ id: 6, name: 'Item 6' },
{ id: 7, name: 'Item 7' },
{ id: 8, name: 'Item 8' },
{ id: 9, name: 'Item 9' },
{ id: 10, name: 'Item 10' }
];
// 获取数据的方法
getData(): any[] {
console.log('DataService: getData() called' + ' ' +this.data.length);
return this.data;
}
// 添加数据的方法
addData(item: any) {
this.data.push(item);
}
// 移除数据的方法
removeData(item: any) {
this.data = this.data.filter(x => x !== item);
}
}
在 Angular 中,@Injectable 装饰器的 providedIn 属性用于指定服务的作用域,即在哪里提供这个服务的实例。providedIn: 'root' 表示该服务是单例的,并且由 Angular 的根模块(通常是 AppModule)提供。
除了root
,providedIn 还可以有以下几种使用方式:
root
:服务作为单例在整个应用程序中只有一个实例。这是默认的提供方式,适用于大多数服务。any
:服务可以在任何模块中提供,并且可以在多个模块中多次提供,每次提供都将创建一个新的实例。platform
:服务只在平台(例如服务器端或 Web Worker)上提供,而不是在浏览器的主渲染线程上。NgModule
:服务在特定的 NgModule 中提供。这意味着服务的实例只在该模块及其导入的模块中可用。module
:后面跟上具体的模块类,例如 providedIn: MyModule,服务只在该模块及其导入的模块中提供。
还可以使用null,实际上是在告诉 Angular 的依赖注入系统不要自动提供这个服务,这样做之后,你需要手动在模块的 providers 数组中注册服务。
csharp
import { Injectable } from '@angular/core';
@Injectable({
providedIn: null // 显式地告诉 Angular 不要自动提供这个服务
})
export class MyService {
// 服务逻辑
}
在模块中手动添加这个服务到 providers 数组中:
csharp
import { NgModule } from '@angular/core';
import { MyService } from './my.service';
@NgModule({
// ... 其他模块元数据
providers: [MyService] // 手动提供服务
})
export class MyModule {
// 模块逻辑
}
使用 providedIn: null
主要有几个用途:
- 控制服务的作用域:你想要控制服务实例的作用域,比如仅在一个特定的模块及其子模块中可用。
- 避免单例模式:虽然 Angular 默认创建服务的单例,但通过手动提供服务,你可以在不同模块中创建服务的多个实例。
- 延迟提供服务:在某些情况下,你可能希望延迟服务的创建,直到它实际上被需要,这可以通过手动提供服务来实现。
- 兼容性:如果你正在维护一个旧的 Angular 应用程序,并且想要保持对旧行为的兼容性,使用 null 可以给你更多的控制。
总的来说,使用 null 提供服务是一种更明确和手动的方法,它允许开发者更精确地控制服务的生命周期和作用域。然而,这也意味着你需要更仔细地管理服务的注册和使用,以避免错误或不一致的行为。
要使用服务,首先需要将其注入到组件中。你可以通过组件的构造函数注入服务:
csharp
constructor(private dataService: DataService) { }
data.component.ts
csharp
import { Component } from '@angular/core';
import { DataService } from '../../services/data.service';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-data',
standalone: true,
imports: [CommonModule],
templateUrl: './data.component.html',
styleUrl: './data.component.css'
})
export class DataComponent {
items: any[]=[];
constructor(private dataService: DataService) { }
ngOnInit() :void{
this.items = this.dataService.getData(); // 调用服务方法获取数据
}
addItem(): void {
let iCount = this.items.length+1;
console.log(iCount);
this.dataService.addData( { id: iCount, name: 'Item ' + iCount})
alert('Item ' + iCount+' 添加成功');
}
removeItem(): void {
if(this.items.length===0)
{
alert('没有数据可删');
return;
}
console.log('删除前'+ this.items.length);
let lastItem = this.items[this.items.length-1];
this.dataService.removeData(lastItem);
this.items = this.dataService.getData();
console.log('删除后'+ this.items.length);
alert(lastItem.name+' 删除成功');
}
}
在imports里面加上CommonModule,不然html里面的*ngFor会有提醒。
data.component.html
csharp
<p>data works!</p>
<div>
<button (click)="addItem()">增加数据</button>
<button (click)="removeItem()">删除数据</button>
</div>
<div *ngFor="let item of items" >
<p>{{ item.name }}</p>
</div>
<!-- @for (item of items; track $index) {
<p>{{ item.name }}</p>
} -->
<p>data works end!</p>
app.component.ts
csharp
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { DataComponent } from './components/data/data.component';
@Component({
selector: 'app-root',
standalone: true,
templateUrl: './app.component.html',
styleUrl: './app.component.css',
imports: [RouterOutlet, DataComponent]
})
export class AppComponent {
title = 'first-component';
}
app.component.html
csharp
<p>这个是app</p>
<app-data></app-data>
运行效果
增加按钮
删除数据