angular基础9-10【依赖注入&服务 Service】

9. 依赖注入

9.1 概述

依赖注入 ( Dependency Injection ) 简称DI,是面向对象编程中的一种设计原则,用来减少代码之间的耦合度

class MailService {
  constructor(APIKEY) {}
}

class EmailSender {
  mailService: MailService
  constructor() {
    this.mailService = new MailService("APIKEY1234567890")
  }

  sendMail(mail) {
    this.mailService.sendMail(mail)
  }
}

const emailSender = new EmailSender()
emailSender.sendMail(mail)

EmailSender 类运行时要使用 MailService 类,EmailSender 类依赖 MailService 类,MailService 类是 EmailSender 类的依赖项。

以上写法的耦合度太高,代码并不健壮。如果 MailService 类改变了参数的传递方式,在 EmailSender 类中的写法也要跟着改变。

class EmailSender {
  mailService: MailService
  constructor(mailService: MailService) {
    this.mailService = mailService;
  }
}
const mailService = new MailService("APIKEY1234567890")
const emailSender = new EmailSender(mailService)

在实例化 EmailSender 类时将它的依赖项通过 constructor 构造函数参数的形式注入到类的内部,这种写法就是依赖注入。

通过依赖注入降了代码之间的耦合度,增加了代码的可维护性。MailService 类中代码的更改再也不会影响 EmailSender 类。

9.2 DI 框架

Angular 有自己的 DI 框架,它将实现依赖注入的过程隐藏了,对于开发者来说只需使用很简单的代码就可以使用复杂的依赖注入功能。

在 Angular 的 DI 框架中有四个核心概念:

  1. Dependency:组件要依赖的实例对象,服务实例对象
  2. Token:获取服务实例对象的标识
  3. Injector:注入器,负责创建维护服务类的实例对象并向组件中注入服务实例对象(管理服务对象的创建和获取)。
  4. Provider:配置注入器的对象,指定创建服务实例对象的服务类和获取实例对象的标识。(Provider:提供程序)

9.2.1 注入器 Injectors

注入器负责创建服务类实例对象,并将服务类实例对象注入到需要的组件中。

  1. 创建注入器

    import { ReflectiveInjector } from "@angular/core"
    // 服务类
    class MailService {}
    // 创建注入器并传入服务类
    const injector = ReflectiveInjector.resolveAndCreate([MailService])
    
  2. 获取注入器中的服务类实例对象

    const mailService = injector.get(MailService)
    
  3. 服务实例对象为单例模式,注入器在创建服务实例后会对其进行缓存

    const mailService1 = injector.get(MailService)
    const mailService2 = injector.get(MailService)
    
    console.log(mailService1 === mailService2) // true
    
  4. 不同的注入器返回不同的服务实例对象

    const injector = ReflectiveInjector.resolveAndCreate([MailService])
    const childInjector = injector.resolveAndCreateChild([MailService])
    
    const mailService1 = injector.get(MailService)
    const mailService2 = childInjector.get(MailService)
    
    console.log(mailService1 === mailService2) // false
    
  5. 服务实例的查找类似函数作用域链,当前级别可以找到就使用当前级别,当前级别找不到去父级中查找

    const injector = ReflectiveInjector.resolveAndCreate([MailService])
    const childInjector = injector.resolveAndCreateChild([])
    
    const mailService1 = injector.get(MailService)
    const mailService2 = childInjector.get(MailService)
    
    console.log(mailService1 === mailService2) // true
    

9.2.2 提供者 Provider

  1. 配置注入器的对象,指定了创建实例对象的服务类和访问服务实例对象的标识。

    const injector = ReflectiveInjector.resolveAndCreate([
      { provide: MailService, useClass: MailService }
    ])
    
  2. 访问依赖对象的标识也可以是字符串类型

    const injector = ReflectiveInjector.resolveAndCreate([
      { provide: "mail", useClass: MailService }
    ])
    const mailService = injector.get("mail")
    
  3. useValue

    const injector = ReflectiveInjector.resolveAndCreate([
      {
        provide: "Config",
        useValue: Object.freeze({
          APIKEY: "API1234567890",
          APISCRET: "500-400-300"
        })
      }
    ])
    const Config = injector.get("Config")
    

将实例对象和外部的引用建立了松耦合关系,外部通过标识获取实例对象,只要标识保持不变,内部代码怎么变都不会影响到外部。

10. 服务 Service

10.1 创建服务

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class TestService { }
export class AppComponent {
 	constructor (private testService: TestService) {}
}

10.2 服务的作用域

使用服务可以轻松实现跨模块跨组件共享数据,这取决于服务的作用域。

  1. 在根注入器中注册服务,所有模块使用同一个服务实例对象。

    import { Injectable } from '@angular/core';
    
    @Injectable({
      providedIn: 'root'
    })
    
    export class CarListService {
    }
    
  2. 在模块级别注册服务,该模块中的所有组件使用同一个服务实例对象。

    import { Injectable } from '@angular/core';
    import { CarModule } from './car.module';
    
    @Injectable({
      providedIn: CarModule,
    })
    
    export class CarListService {
    }
    
    import { CarListService } from './car-list.service';
    
    @NgModule({
      providers: [CarListService],
    })
    export class CarModule {
    }
    
  3. 在组件级别注册服务,该组件及其子组件使用同一个服务实例对象。

    import { Component } from '@angular/core';
    import { CarListService } from '../car-list.service.ts'
    
    @Component({
      selector:    'app-car-list',
      templateUrl: './car-list.component.html',
      providers:  [ CarListService ]
    })
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值