Angular--用工廠方法或值物件來定義提供器
前言
上一篇部落格介紹了注入器和提供器,同時也簡單的講解了一下控制反轉,這篇部落格是使用了工廠方法來定義提供器,所以可以過來了解一下。
內容
這個例子是在提供器方法的例子上建立的:
1.首先刪除product2.component.ts
中的程式碼:
providers:[{
provide:ProductService,useClass:AnotherProductService
}]
最終效果:
import{Component,OnInit}from'@angular/core';
import{Product,ProductService}from'../shared/product.service' ;
import{AnotherProductService}from'../shared/another-product.service';
@Component({
selector:'app-product2',
templateUrl:'./product2.component.html',
styleUrls:['./product2.component.css']
})
exportclassProduct2ComponentimplementsOnInit{
product:Product;
constructor(privateproductService:ProductService){}
ngOnInit(){
this.product=this.productService.getProduct();
}
}
2.在app下的module中修改providers中的內容:
providers:[{
provide:ProductService,
useFactory:()=>{
constlogger=newLoggerService();
constdev=Math.random()>0.5;
if(dev){
returnnewProductService(logger);
}else{
returnnewAnotherProductService(logger);
}
}
},LoggerService],
最終結果:
import{BrowserModule}from'@angular/platform-browser';
import{NgModule}from'@angular/core';
import{FormsModule}from'@angular/forms';
import{HttpModule}from'@angular/http';
import{AppComponent}from'./app.component';
import{Product1Component}from'./product1/product1.component';
import{ProductService}from'./shared/product.service';
import{Product2Component}from'./product2/product2.component';
import{LoggerService}from'./shared/logger.service';
import{AnotherProductService}from'./shared/another-product.service';
@NgModule({
declarations:[
AppComponent,
Product1Component,
Product2Component
],
imports:[
BrowserModule,
FormsModule,
HttpModule
],
providers:[{
provide:ProductService,
useFactory:()=>{
constlogger=newLoggerService();
constdev=Math.random()>0.5;
if(dev){
returnnewProductService(logger);
}else{
returnnewAnotherProductService(logger);
}
}
},LoggerService],
bootstrap:[AppComponent]
})
exportclassAppModule{}
3.在another-product.service.ts
中修改
constructor(publiclogger:LoggerService){}
最終結果:
import{Injectable}from'@angular/core';
import{Product,ProductService}from'./product.service';
import{LoggerService}from'./logger.service';
@Injectable()
exportclassAnotherProductServiceimplementsProductService{
getProduct():Product{
returnnewProduct(1,'iphoneX',9999,'有劉海的蘋果手機');
}
constructor(publiclogger:LoggerService){}
}
4.檢視頁面
刷新出來的效果是兩款商品隨機出現,但是模組中ProductService
中的物件是同一個,即同一次只出現一種效果,然後在現實生活中絕不可能出現這種現象,於是就需要引入宣告
,修改@NgModule
中的內容。具體修改如下:
最終效果:
import{BrowserModule}from'@angular/platform-browser';
import{NgModule}from'@angular/core';
import{FormsModule}from'@angular/forms';
import{HttpModule}from'@angular/http';
import{AppComponent}from'./app.component';
import{Product1Component}from'./product1/product1.component';
import{ProductService}from'./shared/product.service';
import{Product2Component}from'./product2/product2.component';
import{LoggerService}from'./shared/logger.service';
import{AnotherProductService}from'./shared/another-product.service';
@NgModule({
declarations:[
AppComponent,
Product1Component,
Product2Component
],
imports:[
BrowserModule,
FormsModule,
HttpModule
],
providers:[{
provide:ProductService,
useFactory:(logger:LoggerService,appCongig)=>{
if(appConfig.isDev){
returnnewProductService(logger);
}else{
returnnewAnotherProductService(logger);
}
},
deps:[LoggerService,'APP_CONFIG']
},LoggerService,
{
provide:'APP_CONFIG',useVakye:{isDev:false}
}
],
bootstrap:[AppComponent]
})
exportclassAppModule{}
總結
在商品的這個元件裡面在建構函式裡面聲明瞭ProductService的token來注入,Angular看到這個東西以後,就去找token所對應的注入器,然後在app.module.ts中找到了宣告的ProductService,發現這個token是用工廠函式useFactory來進行例項化的,所以會呼叫工廠函式,在呼叫工廠函式的時候發現工廠函式又需要依賴另一個服務:LoggerService,然後LoggerService也是一個token,他需要一個LoggerService的提供器,然後Angular繼續找LoggerService的提供器,根據LoggerService的提供器的宣告來例項化一個LoggerService,如果LoggerService中也有一個工廠,那麼Angular會繼續找下去,直到最後找到了相應的內容生成ProductService的例項,在這個過程中,商品元件裡面的ProductService根本就不需要知道如何去找尋,它只需要知道例項化好了的ProductService是什麼就可以了,然後調取裡面的方法。
end
謝謝您的閱讀!