Angular中创建和使用服务

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>

运行效果

增加按钮


删除数据

相关推荐
cwj&xyp17 分钟前
Python(二)str、list、tuple、dict、set
前端·python·算法
dlnu201525062219 分钟前
ssr实现方案
前端·javascript·ssr
古木201924 分钟前
前端面试宝典
前端·面试·职场和发展
轻口味2 小时前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王2 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发3 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀3 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪3 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef5 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端