Angular中依賴注入
依賴注入:
DI,Dependency injection
控制反轉:
IOC,Inversion of Control
好處:鬆耦合
注入器:
constructor(private productService:ProductService){}
提供器:
providers:[PrpductService]
providers:[{provide:ProductService,useClass:ProductService}]
providers:[{provide:ProductService,useFactory:() =>{}}]
專案
1.1建立專案
–> ng new di
1.2生成元件
–> ng g component product1
1.3生成服務
–> ng g service shared/product
提供器宣告在模組中
product.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ProductService {
constructor() { }
getProduct(): Product {
return new Product(0, 'iphobeX', 10000, '最新款蘋果手機');
}
}
export class Product {
constructor(
public id: number,
public title: string,
public price: number,
public desc: string
) {
}
}
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { Product1Component } from './product1/product1.component' ;
import {ProductService} from './shared/product.service';
@NgModule({
declarations: [
AppComponent,
Product1Component
],
imports: [
BrowserModule
],
/*使用提供器宣告在模組裡*/
providers: [ProductService],
bootstrap: [AppComponent]
})
export class AppModule { }
product1.component.ts
import { Component, OnInit } from '@angular/core';
import {Product, ProductService} from '../shared/product.service';
@Component({
selector: 'app-product1',
templateUrl: './product1.component.html',
styleUrls: ['./product1.component.css']
})
export class Product1Component implements OnInit {
/*接收從服務中獲取資料*/
product: Product;
/*依賴注入宣告所需服務*/
constructor(private productService: ProductService) { }
ngOnInit() {
this.product = this.productService.getProduct();
}
}
product1.component.html
<div>
<h1>商品詳情</h1>
<h2>名稱:{{product.title}}</h2>
<h2>價格:{{product.price}}</h2>
<h2>描述:{{product.desc}}</h2>
</div>
app.component.html
<div>
<div>
<h1>基本的依賴注入樣例</h1>
</div>
<div>
<app-product1></app-product1>
</div>
</div>
1.2生成元件
–> ng g component product2
1.3生成服務
–> ng g service shared/anotherProduct
提供器宣告在元件中
another-product.service.ts
import { Injectable } from '@angular/core';
import {Product, ProductService} from './product.service';
import {LoggerService} from './logger.service';
@Injectable({
providedIn: 'root'
})
/*實現ProductService*/
export class AnotherProductService implements ProductService {
logger: LoggerService;
getProduct(): Product {
return new Product(1, 'sumsung', 4899, '最新款三星手機');
}
constructor() { }
}
product2.component.ts
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'],
/*使用提供器宣告在元件裡*/
providers: [{
provide: ProductService, useClass: AnotherProductService
}]
})
export class Product2Component implements OnInit {
/*接收從服務中獲取資料*/
product: Product;
/*依賴注入宣告所需服務*/
constructor(private productService: ProductService) { }
ngOnInit() {
this.product = this.productService.getProduct();
}
}
product2.component.html
<div>
<h1>商品詳情</h1>
<h2>名稱:{{product.title}}</h2>
<h2>價格:{{product.price}}</h2>
<h2>描述:{{product.desc}}</h2>
</div>
app.component.html
<div>
<div>
<h1>基本的依賴注入樣例</h1>
</div>
<div>
<app-product1></app-product1>
<app-product2></app-product2>
</div>
</div>
規則:
1.當提供器宣告在模組中時,所有元件可見
2.當提供器宣告在元件中時,本元件、子元件可見
3.當宣告在模組中的提供器和宣告在元件中的提供器具有相同的token時,宣告在元件中的提供器會覆蓋宣告在模組中提供器。
4.優先考慮在模組中宣告提供器。
服務中注入服務
1.在模組中宣告
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
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';
@NgModule({
declarations: [
AppComponent,
Product1Component,
Product2Component
],
imports: [
BrowserModule
],
/*使用提供器宣告在模組裡*/
providers: [ProductService, LoggerService],
bootstrap: [AppComponent]
})
export class AppModule { }
2.loggerService 注入到productService
logger.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LoggerService {
constructor() { }
log(message: string) {
console.log(message);
}
}
logger.service.ts
import { Injectable } from '@angular/core';
import {LoggerService} from './logger.service';
@Injectable({
providedIn: 'root'
})
export class ProductService {
constructor(private logger: LoggerService) { }
getProduct(): Product {
this.logger.log('getProduct方法被呼叫');
return new Product(0, 'iphobeX', 10000, '最新款蘋果手機');
}
}
export class Product {
constructor(
public id: number,
public title: string,
public price: number,
public desc: string
) {
}
}
用工廠方法和值宣告提供器
product2.component.ts
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'],
/*去掉元件宣告提供器,和1共享module宣告提供器*/
/*providers: [{
provide: ProductService, useClass: AnotherProductService
}]*/
})
export class Product2Component implements OnInit {
/*接收從服務中獲取資料*/
product: Product;
/*依賴注入宣告所需服務*/
constructor(private productService: ProductService) { }
ngOnInit() {
this.product = this.productService.getProduct();
}
}
another-product.service.ts
import { Injectable } from '@angular/core';
import {Product, ProductService} from './product.service';
import {LoggerService} from './logger.service';
@Injectable({
providedIn: 'root'
})
/*實現ProductService*/
export class AnotherProductService implements ProductService {
logger: LoggerService;
getProduct(): Product {
return new Product(1, 'sumsung', 4899, '最新款三星手機');
}
constructor(public logger: LoggerService) { }
}
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
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
],
/*使用提供器宣告在模組裡*/
providers: [{
provide: ProductService,
useFactory: () => {
const logger = new LoggerService();
const dev = Math.random() > 0.5;
if (dev) {
return new ProductService(logger);
} else {
return new AnotherProductService(logger);
}
}
}, LoggerService],
bootstrap: [AppComponent]
})
export class AppModule { }
注:工廠方法建立的物件是一個單例物件,只在建立第一需要注入的物件時被呼叫一次,在整個應用中
降耦合:app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
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
],
/*使用提供器宣告在模組裡*/
providers: [{
provide: ProductService,
useFactory: (logger: LoggerService) => {
const dev = Math.random() > 0.5;
if (dev) {
return new ProductService(logger);
} else {
return new AnotherProductService(logger);
}
},
deps: [LoggerService]
}, LoggerService],
bootstrap: [AppComponent]
})
export class AppModule { }
用一個具體的值來定義一個提供器
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
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
],
/*使用提供器宣告在模組裡*/
providers: [{
provide: ProductService,
useFactory: (logger: LoggerService, isDev) => {
if (isDev) {
return new ProductService(logger);
} else {
return new AnotherProductService(logger);
}
},
deps: [LoggerService, 'IS_DEV_ENV']
}, LoggerService,
{
provide: 'IS_DEV_ENV', useValue: false
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
用一個值物件來定義一個提供器
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
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
],
/*使用提供器宣告在模組裡*/
providers: [{
provide: ProductService,
useFactory: (logger: LoggerService, appConfig) => {
if (appConfig.isDev) {
return new ProductService(logger);
} else {
return new AnotherProductService(logger);
}
},
deps: [LoggerService, 'APP_CONFIG']
}, LoggerService,
{
provide: 'APP_CONFIG', useValue: {isDev: false}
}
],
bootstrap: [AppComponent]
})
export class AppModule { }