Angular4.0从入门到实战打造在线竞拍网站学习笔记之三--依赖注入

Angular4.0基础知识之组件
Angular4.0基础知识之路由
Angular4.0依赖注入
Angular4.0数据绑定&管道html

依赖注入(Dependency Injection)

正常状况下,咱们写的代码应该是这样子的:typescript

let product = new Product();    // 实例化一个对象
createOrder(product);   // 调用方法传入商品对象,生成订单

createOrder方法依赖product类,可是createOrder方法自身并不知道也不能去建立一个product对象。咱们把方法所需的对象实例化并当作参数传入,这个过程就成为把参数注入给这个方法。在此你可能看不出什么,可是若是依赖的对象比较多了呢?咱们须要反复去new,反复去生成对象,而后传入到方法中......想一想就是噩梦。app

那么,能不能让某人替咱们建立createOrder所依赖的对象和对象所依赖的其余对象呢?若是能够的话,那么,咱们只须要写一句方法的调用便可,对象都将会呗自动建立好,并当作参数传递进去(想一想就很美妙,懒人必备啊)。框架

也就是说,对象A只须要声明,我须要一个B类型的对象,那么这个对象就会从外部注入进来,这就是依赖注入要解决的问题。dom

与依赖注入常常同时出现的另外一个概念叫作控制反转(Inversion Of Control),简称IOC。ide

控制反转是指将依赖的控制权从代码的内部转移到代码的外部,如上代码所示,方法所需的依赖是由方法的内部所决定的,若是须要改变依赖,就须要修改方法内部的代码,外面无论是传入Product的实例,仍是传入Product子类的实例,是有方法外部决定的。函数

IOC着重描述目的;DI着重描述实现的方法,即如何去实现控制反转。实现了控制反转模式的框架被称为IOC容器。工具

实现依赖注入

那么如何在Angular中实现以来注入呢?this

定义提供器

首先,使用命令行工具生成一个service,用于提供注入服务。命令行

ng g service shared/product

因为product是共享的,因此放到了一个自定义的shared文件夹

接下来,对生成的服务进行编辑(因为当前没有对这个服务进行注册,显然不会生效)

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

@Injectable()
export class ProductService {

  constructor() { }

  getProduct(): Product {
    return new Product(1, '小米Mix', 3999, '很666的手机');
  }

}

/**
 * 定义一个Product商品类
 */
export class Product {
  constructor(public id: number, public title: string, public price: number, public desc: string) { }
}

下面,进入app.module,注册服务

...
  providers: [ProductService],
...

在使用的时候(须要获取product对象的时候,直接在构造函数中声明须要Product类型的变量,便可完成注入。

constructor (product:Product){  }

这时候,注入提供器声明在了模块中,也能够在组件的@component()中添加providers属性,这时候,做用域就变成了当前组件,而且组件中声明的提供器比模块的优先级更高

使用工厂声明提供器

若是在实例化类的时候须要传递参数,或须要进行一些操做去获得一个注入对象,那么使用工厂声明一个提供器是更好的解决办法。

providers: [{
    provide: ProductService,
    useFactory: () => {
      const dev = Math.random() > 0.5;
      if (dev) {
        return new Product(1, '小米6', 2999, '很6的手机');
      } else {
        return new Product(2, '小米mix', 3999, '很美的手机');
      }
    }
  }],

那么,若是工厂方法依赖一个LoggerService,咱们如何去解耦合并把loggerServices注入到工厂方法呢?须要使用第三个参数:

providers: [{
    provide: ProductService,
    useFactory: (logger:LoggerService) => {
      const dev = Math.random() > 0.5;
      if (dev) {
        return new Product(1, '小米6', 2999, '很6的手机');
      } else {
        return new Product(2, '小米mix', 3999, '很美的手机');
      }
    },
    deps:[LoggerService]
  },LoggerService],

如此,便可实现工厂方法的依赖注入

使用具体的值定义提供器

providers: [{
    provide: ProductService,
    useFactory: (logger:LoggerService,appConfig) => {
      if (appConfig.isDev) {
        return new Product(1, '小米6', 2999, '很6的手机');
      } else {
        return new Product(2, '小米mix', 3999, '很美的手机');
      }
    },
    deps:[LoggerService,"APP_CONFIG"]
  },LoggerService,{
    provide:"APP_CONFIG",
    useValue:{isDev:false}
  }],

注意,被注入的类都须要有一个@Injectable()装饰器,这样才能被注入

那么你可能会疑惑了,angular组件控制器的类并无@Injecdtable()装饰器,可是构造函数却能被注入,这是由于@component()装饰器的实现一键集成了@Injectable()

为了更容易理解,接下来实现一下手工注入:

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

export class ProductComponent implements OnInit {

  private product: ProductService;

  constructor(private injector: Injector) {
    this.product = injector.get(ProductService);
  }
}

Angular的依赖注入只有一个注入点,也就是构造函数。

相关文章
相关标签/搜索