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 { }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章