欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

如何创建 Angular 服务?组件中注入服务的方法

程序员文章站 2022-06-26 11:42:59
服务一般用来放置可复用的代码。 如何创建 Angular 服务 在 Angular 中我们通过以下方式创建一个简单的服务: export class BookServic...

服务一般用来放置可复用的代码。

如何创建 Angular 服务

在 Angular 中我们通过以下方式创建一个简单的服务:

export class BookService {
    getBooks() {
        return ['Angular', 'React', 'Vue'];
    }
}

我们来创建一个新的组件 BookComponent,它用来显示书籍的信息:

// book.component.ts
export class BookComponent implements OnInit {
    books: Array<{ id: number; name: string }>;

    ngOnInit() {
        this.books = [
            { id: 11, name: 'Angular' },
            { id: 12, name: 'React' },
            { id: 13, name: 'Vue' }
        ];
    }
}

// book.component.html
  • ID: {{ book.id }} - Name: {{ book.name }}

  在 BookComponent 组件中,我们在 ngOnInit 钩子中进行数据初始化,然后利用 ngFor 指令来显示书籍列表的信息。创建完 BookComponent 组件,我们来验证一下该组件的功能。

  因为我是用 Angular CLI 脚手架创建的组件,所以已自动导入 AppModule,只需要记得在 app.component.html 中将内容更改为 即可。不出意外的话,访问 https://localhost:4200/ 将会看到

ID: 11 - Name: Angualr ID: 12 - Name: React ID: 13 - Name: Vue

目前我们实现的书籍信息是固定的,别忘了,在实际的开发场景中,一般需要从远程服务器获取相应的信息。但我们暂不考虑这个问题,假设另外一个组件也需要利用同样的书籍信息,那我们要怎么办,总不可能用复制粘贴~

接下来我们创建一个 BookService 服务,从而实现数据共享。

// book.service.ts
export class BookService {

  books: Array<{ id: number; name: string}> = [
    { id: 11, name: "Angular" },
    { id: 12, name: "React" },
    { id: 13, name: "Vue" }
  ];

  getBooks() {
    return this.books;
  }

}

在 BookService 服务中,我们定义了一个 books 属性和一个 getBooks() 方法:

books - 用于保存书籍的信息 getBooks() - 用于获取书籍的信息

创建完 BookService 服务后,就要使用它了!

组件中使用服务

主要分为三个步骤:

1)导入服务

// book.component.ts
import { BookService } from '../book.service';

2)声明服务

方式一:

// book.component.ts
@Component({
    selector: 'app-book',
    ...
    providers: [BookService]
})

方式二:

// app.module.ts
@NgModule({
    ...
    providers: [BookService],
    ...
})

注意:不管哪种方式,记得一定要在文件头 import 进服务。

3)注入服务

// book.component.ts
export class BookComponent implements OnInit {
    constructor(private bookService: BookService) {}
}

问题1:可能会有人疑惑为什么去掉 private 会报错?

这里解释下,这是 TypeScript 的用法,跟 Java 类似,分别是 public、private、protected。

上述例子可以等价为:

// book.component.ts
export class BookComponent implements OnInit {
    private bookService: BookService;
    constructor(bookService: BookService) {
        this.bookService = bookService;
    }
}

问题2:为什么配置完 BookService,在 BookComponent 组件类中构造函数中还得进行类型声明?

因为在 @NgModule({...}) 或 @Component({...}) 的元数据中我们只是配置了 Provider 的相关信息,即告诉 Angular DI(依赖注入)系统,如何创建根据配置的 provider 信息,创建相应的依赖对象。而在 BookComponent 组件类中,我们通过构造注入的方式去告诉 Angular DI 系统,我们需要的依赖对象**类型。

|| 至此,我们只是勉强完成了服务,这样就OK了?当然不行!

下面来解决实际开发中遇到处理数据时如玩服务~

在这里模拟一个书籍列表,创建 book.json 并放置在 /assets/json/book.json 中:

{
    "books": [
        {
            "name": "Angular"
        },
        {
            "name": "React"
        },
        {
            "name": "Vue"
        }
    ]
}

修改 book.service.ts :

// book.service.ts
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';

@Injectable()
export class BookService {

    constructor(private http: Http) {}

    private handleError(error: any): Promise {
        console.error('An error occurred' + error);
    }

    getBooks() {
        const url = '/assets/json/book.json';
        return this.http.get(url).toPromise().then(res => res.json()).catch(this.handleError);
    }
}

注:默认情况下,Angular 的Http服务返回一个 RxJS 的Observable对象。 我们可以通过 toPromise() 方法将其转为便捷的承诺Promise。 使用 toPromise() 方法时要引入:

import 'rxjs/add/operator/toPromise';

接下来使用这个 BookService 服务:

// book.component.ts
import { Component, OnInit } from '@angular/core';
import { BookService } from '../book.service';

@Component({
  selector: 'app-book',
  templateUrl: './book.component.html',
  styleUrls: ['./book.component.css'],
  providers: [BookService]
})
export class BookComponent implements OnInit {

  constructor(private bookService: BookService) {

  };

  books: any[];

  ngOnInit() {
    this.bookService.getBooks().then(res => {this.books = res.books};
  }

}

常用服务

获取(get)数据:

get() {   
  return this.http.get(url)   
         .toPromise()   
         .then(response => response.json() )   
         .catch(this.handleError);  
}     

private handleError(error: any): Promise {   
  console.error('An error occurred', error);
}

新建(post)数据:

private headers = new Headers({'Content-type': 'application/json'});   

create() {   
  return this.http   
         .post(url, JSON.stringify(hero), {headers: this.headers})   
         .toPromise()   
         .then(response => response.json())   
         .catch(this.handleError);  
}

更新(update)数据:

private headers = new Headers({'Content-type': 'application/json'});   

update() {   
  return this.http   
         .put(url, JSON.stringify(hero), {headers: this.headers})   
         .toPromise()   
         .then(response => response.json())   
         .catch(this.handleError);  
}

删除(delete)数据:

private headers = new Headers({'Content-type': 'application/json'});   

delete() {   
  return this.http
        .delete(url, {headers: this.headers})   
        .toPromise()   
        .then(() => null)   
        .catch(this.handleError);  
}