常见的后端开发中,有个MVC开发模式:Model-View-Controller。在MVC架构中,有个service层,负责是连接Controller和Model。Controller处理用户的输入和请求,Service负责从Model中获取数据并处理数据,Model定义数据库的字段定义和一些行为。在Angular中,Service作为一个服务,和MVC中的Service相类似,但是还是有差别的。
说起Angular,不得不说下MVVM设计模式:Model-View-ViewModel。
- Model数据层,它是与应用程序的业务逻辑相关的数据的封装载体,在web页面中,大部分Model都是来自请求的服务端返回单数据或者是全局配置的对象。Angular中service则是封装和处理这些Model相关的业务逻辑的所在。
- View视图,声明式模板,专注于界面的显示和渲染。
- ViewModel视图-数据,它是View和Model的黏合体,负责View和Model的交互和协作。利用框架内置的双向绑定技术来实现View和Model的粘合。
为什么我们需要Service?
Angular的service是一个简单的TypeScript类,它封装了一些用于完成应用程序中特定任务的方法,例如从服务器获取数据或者向服务器发送数据。
Angular Service 具有以下的作用:
- 用来将应用程序中的业务逻辑组件中的渲染逻辑分离
- 用来在Angular应用中的多个组件之间共享数据
- 让程序易于测试和调试
- 用于编写可重用的代码。
创建一个Service
声明一个Service,需要使用Angular Core
包提供的@Injectable
装饰器,这意味着该服务可以被注入到组件和其他服务中。
我们可以使用Angular cli
命令行创建一个服务:
1 | ng g s auth |
这样就创建了一个文件名为:auth.server.ts
文件,里面有一个类:AuthService
,看看里面具体的内容:
1 | import {Injectable} from '@Angular/core'; |
Injectable元数据提供了一个providedIn
属性告诉Angular 注入器我们这个类的作用域以及他可以被注入到哪里。
@Injectable
为标记性元数据,表示一个类可以由Injector
创建。可以接受的选项有providedIn
,这个参数描述了这个类的注入等级。providedIn
接受的值有:
root
将服务注入到根组件中,这样它是全局共享的一个单例服务。platform
页面所有应用程序共享的特殊单例平台注入器。any
可以是任何Angular Module
Service可以被注入到root
或者其他任何可用Module(使用any
或直接使用Module)。any
是Angular9版本开始支持。
我们可以给这个服务增加一个方法,从服务器中获取用户数据。
为了发送Http请求,我们需要导入HttpClientModule
来注入HttpClient
服务,我们需要src/app.component.ts
中的import
数组中添加HttpClientModule
:
1 | import {BrowserModule} from '@angular/platform-browser'; |
HttpClient
也是一个服务,我们可以将它注入到我们的AuthService
中:
1 | import {Injectable} from '@angular/core'; |
服务提供商配置注入器
我们前面创建的类提供了一个服务,@Injectable
装饰器把它标记为可注入的服务。但是在我们使用服务的provider
提供商配置好Angular依赖注入器之前,Angular无法将其注入到任何位置。
前面我们创建的服务:AuthService
,为什么我们没有配置provider
注入器,但是可以在组件中使用呢?
是因为在创建的时候默认将providedIn
配置为root
,这就创建了一个当前应用程序全局的服务。我们可以在任何组件里面使用,而不用特意在组件或模块中声明provider
。
可以在以下三种位置之一设置元数据,以便在应用的不同层级使用提供商来配置注入器:
- 服务本身的
@Injectable
装饰器providedIn
元数据中设置。 - 在
NgModule
的@NgModule
装饰器providers
元数据中设置,模块级的注入器。 - 在组件的
@Component
装饰器providers
元数据中设置,组件级的注入器。
所有的组件都是指令,而providers
选项是从@Directive
中继承来的,所以也可以与组件一样的级别为指令、管道配置服务提供商。
注入一个Service
先来了解下DI
(Dependency Injection 依赖注入),DI是一种编码模式,一个类请求从外部资源中提供依赖关系,而不是去自己创建它们。
注入服务意味着什么?
Angular使用Dependency Injection
(依赖注入,DI)来提供Service的实例给组件或者其他服务,这意味我们在使用这个服务之前无需手动去创建它;我们只需要告诉依赖注入(DI)我们需要使用这个服务,这样依赖注入会给我们提供这个服务的实例。那么我们如何告诉DI我们需要使用这个服务?
我们仅需要在组件或服务的构造函数中定义需要注入的服务,通过带有依赖类型的构造函数参数来要求Angular在组件的构造函数中注入依赖项。
我们在AppComponent
中使用AuthService
:
1 | import {Component, OnInit} from '@angular/core'; |
可以看到,我们直接在组件中的constructor
方法中声明我们需要的服务就可以使用这个服务,而不用创建这个服务。
这里我们了解了基本的Angular的Service的声明和注入,在使用上有全局的单例模式和模块或组件的注入模式。篇幅较长,服务的分级注入另写一篇。