Angular4.0從入門到實戰打造在線競拍網站學習筆記之三--依賴注入


Angular4.0基礎知識之組件
Angular4.0基礎知識之路由
Angular4.0依賴注入
Angular4.0數據綁定&管道

依賴注入(Dependency Injection)

正常情況下,我們寫的代碼應該是這樣子的:

let product = new Product();	// 實例化一個對象
createOrder(product);	// 調用方法傳入商品對象,生成訂單

createOrder方法依賴product類,但是createOrder方法自身並不知道也不能去創建一個product對象。我們把方法所需的對象實例化並當做參數傳入,這個過程就成為把參數注入給這個方法。在此你可能看不出什么,但是如果依賴的對象比較多了呢?我們需要反復去new,反復去生成對象,然后傳入到方法中......想想就是噩夢。

那么,能不能讓某人替我們創建createOrder所依賴的對象和對象所依賴的其他對象呢?如果可以的話,那么,我們只需要寫一句方法的調用即可,對象都將會唄自動創建好,並當做參數傳遞進去(想想就很美妙,懶人必備啊)。

也就是說,對象A只需要聲明,我需要一個B類型的對象,那么這個對象就會從外部注入進來,這就是依賴注入要解決的問題。

與依賴注入經常同時出現的另一個概念叫做控制反轉(Inversion Of Control),簡稱IOC。

控制反轉是指將依賴的控制權從代碼的內部轉移到代碼的外部,如上代碼所示,方法所需的依賴是由方法的內部所決定的,如果需要改變依賴,就需要修改方法內部的代碼,外面不管是傳入Product的實例,還是傳入Product子類的實例,是有方法外部決定的。

IOC着重描述目的;DI着重描述實現的方法,即如何去實現控制反轉。實現了控制反轉模式的框架被稱為IOC容器。

實現依賴注入

那么如何在Angular中實現以來注入呢?

定義提供器

首先,使用命令行工具生成一個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的依賴注入只有一個注入點,也就是構造函數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM