Angular4.0基礎知識之組件
Angular4.0基礎知識之路由
Angular4.0依賴注入
Angular4.0數據綁定&管道html
正常狀況下,咱們寫的代碼應該是這樣子的: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的依賴注入只有一個注入點,也就是構造函數。