服务并没有一个明确的定义,在 Angular 的应用中,比较推荐的做法是,把诸如从服务器获取数据、验证用户输入等工作委托给各种服务,而组件主要用于提供有关绑定数据到模板的属性和方法。
将组件和服务分开,可以有效提高代码的复用性。
依赖注入不是一种技术,而是一种编程思想,能够帮助开发者设计出松耦合、可扩展、便于复用的系统。
所谓依赖,在 Angular 中,主要指服务,通过把各种服务配置到(注入的过程)模块或组件中,来共同完成业务逻辑。
下面是已经创建好的服务文件 login.service.ts:
例子:
// 引入装饰器 Injectable import { Injectable } from '@angular/core'; // providedIn:将服务注入到组件或模块中 // 默认值为 root,即注入到根模块,整个应用都可以访问 @Injectable({ providedIn: 'root' }) export class LoginService { constructor() { } // 添加一个方法 getName(){ return 'Tom'; } }
下图是从宏观上观察一下服务与组件、子路由、特性模块之间的关系:
注入服务大致可以分为以下三种形式:
1、注入到根模块
例子:
服务文件:login.service.ts
import { Injectable } from '@angular/core'; // 将服务注入到根模块 // 整个应用都可以访问到 @Injectable({ providedIn: 'root' }) export class LoginService { constructor() { } getName(){ return 'Tom'; } }
使用服务的组件:login.component.ts
import { Component, OnInit } from '@angular/core'; // 导入服务 import { LoginService } from '../service/login.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'] }) export class LoginComponent implements OnInit { // 此处非常重要 // 在构造函数中声明 LoginService 服务 constructor( private loginService:LoginService, ) { } ngOnInit() { // 使用 LoginService 服务 console.log(this.loginService.getName()); } }
2、注入到特性模块
例子:
服务文件:login.service.ts
import { Injectable } from '@angular/core'; // 将 providedIn: 'root' 删除 @Injectable() export class LoginService { constructor() { } getName(){ return 'Tom'; } }
在特性模块中注入需要的服务:login.module.ts
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { LoginRoutes, Components } from './login.routing'; // 在特性模块中导入服务 import { LoginService } from './service/login.service'; @NgModule({ imports: [ CommonModule, LoginRoutes ], declarations: [...Components], // 在 providers 中注入 LoginService providers: [ LoginService ], }) export class LoginModule { }
使用服务的组件:login.component.ts
import { Component, OnInit } from '@angular/core'; // 导入服务 import { LoginService } from '../service/login.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'] }) export class LoginComponent implements OnInit { // 此处非常重要 // 在构造函数中声明 LoginService 服务 constructor( private loginService:LoginService, ) { } ngOnInit() { // 使用 LoginService 服务 console.log(this.loginService.getName()); } }
3、注入到组件
例子:
服务文件:login.service.ts
import { Injectable } from '@angular/core'; // 将 providedIn: 'root' 删除 @Injectable() export class LoginService { constructor() { } getName(){ return 'Tom'; } }
直接在组件中注入需要的服务:login.component.ts
import { Component, OnInit } from '@angular/core'; // 导入服务 import { LoginService } from '../service/login.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'], // 在 providers 中注入 LoginService 服务 providers: [ LoginService ], }) export class LoginComponent implements OnInit { // 此处非常重要 // 在构造函数中声明 LoginService 服务 constructor( private loginService:LoginService, ) { } ngOnInit() { // 使用 LoginService 服务 console.log(this.loginService.getName()); } }
通常情况下,注入到根模块中的服务,是整个 Angular 应用都需要的服务,具有全局作用域;
而注入到特性模块中的服务,只能为这个模块下的所有组件提供服务;
如果是在组件中注入服务,那么只会在该组件及其子组件中有效,同一模块中的其它组件无法访问。
与在组件中使用服务的模式相同。
例子:
需要引入其他服务的服务文件:login.service.ts
import { Injectable } from '@angular/core'; // 导入 ApiService 服务 import { ApiService } from '../../common/api.service'; @Injectable() export class LoginService { constructor( // 声明 ApiService 服务 private api:ApiService ) { } getName(){ // 使用 ApiService 服务 return this.api.getJson(); } }
end