欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Angular中依賴注入怎么用-創(chuàng)新互聯(lián)

這篇文章主要介紹了Angular中依賴注入怎么用,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

10年積累的網(wǎng)站設計制作、網(wǎng)站設計經(jīng)驗,可以快速應對客戶對網(wǎng)站的新想法和需求。提供各種問題對應的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡服務。我雖然不認識你,你也不認識我。但先制作網(wǎng)站后付款的網(wǎng)站建設流程,更有米易免費網(wǎng)站建設讓你可以放心的選擇與我們合作。

一、什么是依賴注入

控制反轉(IoC)

控制反轉的概念最早在2004年由Martin Fowler提出,是針對面向對象設計不斷復雜化而提出的一種設計原則,是利用面向對象編程法則來降低應用耦合的設計模式。

IoC強調的是對代碼引用的控制權由調用方轉移到了外部容器,在運行是通過某種方式注入進來,實現(xiàn)了控制反轉,這大大降低了程序之間的耦合度。依賴注入是最常用的一種實現(xiàn)IoC的方式,另一種是依賴查找。

依賴注入(Dependency Injection)

當然,按照慣例我們應該舉個例子, 哦對,我們主要說明的是依賴注入,依賴查找請自行查閱資料。

假設我們有一個能做漢堡的設備(HRobot),需要用肉(meat)和一些沙拉(salad)作為原料,我們可以這樣實現(xiàn):

export class HRobot {
  public meat: Meat;
  public salad: Salad;
  constructor() {
    this.meat = new Meat();
    this.salad = new Salad();
  }
  cook() {}
}

看一下好像沒有什么問題,可能你已經(jīng)發(fā)現(xiàn),我們的原材料都是放在機器里面的,如果我們想吃別的口味的漢堡恐怕就要去鄉(xiāng)村基了。

為了可以吃到別的口味的漢堡,我們不得不改造一下我們的HRobot:

export class HRobot {
  public meat: Meat;
  public salad: Salad;
  constructor(public meat: Meat, public salad: Salad) {
    this.meat = meat;
    this.salad = salad;
  }
  cook() {}
}

現(xiàn)在,只要要直接給它meat和salad就好了,我們的HRobot()并不需要知道給它的是什么樣的meat:

let hRobot = new HRobot(new Meat(), new Salad());

比如,我們想吃雞肉漢堡,只需要個它一塊雞肉就好:

class Chicken extends Meat {
  meat = 'chiken';
}

let cRobot = new HRobot(new Chicken(), new Salad());

感覺還不錯,我們再也不會為了吃一個雞肉漢堡大費周章的去改造一臺機器,這太不可思議了。

我可能想到了,你還是懶得弄塊雞肉給它,這時候可以使用工廠函數(shù):

export class HRobotFactory {
  createHRobot() {
    let robot = new HRobot(this.createMeat(), this.createSalad());
  }

  createMeat() {
    return new Meat();
  }

  creatSalad() {
    return new Salad();
  }
}

現(xiàn)在有了工廠,就有源源不斷的漢堡可以吃了,開不開心,驚不驚喜?

好吧,沒有最懶,只有更懶,連工廠都懶得管理我也是無話可說,幸運的是我們有Angular提供的依賴注入框架,它可以讓你伸手就有漢堡吃!

二、 Angular依賴注入

在介紹Angular依賴注入之前,先來理一下三個概念:

  1. 注入器(Injector):就想制造工廠,提供了一系列的接口,用于創(chuàng)建依賴對象的實例。

  2. 提供商(Provider):用于配置注入器,注入器通過它來創(chuàng)建被依賴對象的實例,Provider把令牌(Token)映射到工廠方法,被依賴的對象就是通過這個方法創(chuàng)建的。

  3. 依賴(Denpendence):指定了被依賴對象的類型,注入器會根據(jù)此類型創(chuàng)建對應的對象。

說了半天到底是什么樣的?

Angular中依賴注入怎么用

用代碼示例如下:

var injector = new Injector(...);
var robot = injector.get(HRobot);
robot.cook();

Injector()的實現(xiàn)如下:

import { ReflecttiveInjector } form '@angular/core';

var injector = ReflectiveInjector.resolveAndCreat([
  {provide: HRobot, useClass: HRobot},
  {provide: Meat, useClass: Meat},
  {provide: Salad, useClass: Salad}
]);

還有注入器是這樣知道知道初始化HRobot需要依賴Meat和Salad:

export class Robot {
  //...
  consructor(public meat: Meat, public salad: Salad) {}
  //...
}

當然,看了頭大是應該的,因為上面的東西壓根就不需要自己動手寫,Angular的依賴注入框架已經(jīng)自動幫我們完成了(注入器的生成和調用)。

1. 在組件中注入服務

Angular在底層做了大量的初始化工作,這極大地降低了我們使用依賴注入的成本,現(xiàn)在要完成依賴注入,我們只需要三步:

  1. 通過import導入被依賴的對象服務

  2. 在組件中配置注入器。在啟動組件時,Angular會讀取@Component裝飾器里的providers元數(shù)據(jù),它是一個數(shù)組,配置了該組件需要使用的所有依賴,Angular的依賴注入框架會根據(jù)這個列表去創(chuàng)建對應的示例。

  3. 在組件構造函數(shù)中聲明需要注入的依賴。注入器會根據(jù)構造函數(shù)上的聲明,在組件初始化時通過第二步中的providers元數(shù)據(jù)配置依賴,為構造函數(shù)提供對應的依賴服務,最終完成依賴注入。

例子來了:

// app.component.ts
//...
// 1. 導入被依賴對象的服務
import { MyService } from './my-service/my-service.service';

@Component({
  //...
  // 2. 在組件中配置注入器
  providers: [
    MyService
  ]
  //...
})

export class AppComponent {
  // 3. 在構造函數(shù)中聲明需要注入的依賴
  constructor(private myService: MyService) {}
}

2. 在服務中注入服務

除了組件依賴服務,服務間依的相互調用也很寒常見。例如我們想給我們的漢堡機器人加上一個計數(shù)器,來記錄它的生產(chǎn)狀況,但是計數(shù)器又依靠電源來工作,我們就可以用一個服務來實現(xiàn):

// power.service.ts

import { Injectable } from '@angular/core';

@Injectable()
export class PowerService {
  // power come from here..
}


// count.service.ts

import { Injectable } from '@angular/core';
import { PowerService } from './power/power.service';

@Injectable()
export class CountService {
  constructor(private power: PoowerService) {}
}

// app.component.ts  這里是當前組件,其實模塊中的注入也一樣,后面講到
//...
providers: [
  CountService,
  PowerService
]

這里需要注意的是@Injectable裝飾器是非必須的,因為只有一個服務依賴其他服務的時候才必須需要使用@Injectable顯式裝飾,來表示這個服務需要依賴,所以我們的PowerService并不是必須加上@Injectable裝飾器的,可是,Angular官方推薦是否依賴其他服務,都應該使用@Injectable來裝飾服務。

3. 在模塊中注入服務

在模塊中注冊服務和在組件中注冊服務的方法是一樣的,只是在模塊中注入的服務在整個組件中都是可用的。

// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
@NgModule({
 declarations: [
  AppComponent,
 ],
 imports: [
  BrowserModule
 ],
 providers: [CountService, PowerService],
 bootstrap: [AppComponent]
})
export class AppModule { }

與在組件中注入不同的是,在Angular應用啟動的時候,它好首先加載這個模塊需要的所有依賴,,此時會生成一個全局的根注入器,由該依賴創(chuàng)建的依賴注入對象會再整個應用中可見,并共享一個實例。

Angular沒有模塊級作用域這個概念,只有應用程序級作用域和組件級作用域,這種設計主要是考慮模塊的擴展性,一個應用通常由多個模塊合并和成,在@NgModule中注冊的服務,默認在整個應用中可用。

下面說兩種特殊情況:

假設在兩個模塊中使用同樣的Token注入了同一個服務,并且這兩個模塊先后導入到了根組件中:

// ...
@NgModule({
imports: [
 AModule,
 BModule
]
// ...
})

那么后面導入的模塊中的服務會覆蓋前面導入模塊中的服務,也就是說BModule中的服務會覆蓋AModule中的服務,即使是在AModule中注入的服務,同樣使用的是BMoudle中提供的實例。

還是假設兩個模塊同樣使用同一個Token注入了同一個服務,但是BModule模塊是導入在AModule模塊中的:

// a.module.ts
// ...
@NgModule({
 imports: [BModule]
})

那么這種情況下兩個模塊使用的都是AModule中注入的服務。可以推斷出在根模塊中注入的服務是擁有最高優(yōu)先級的,你可以在任何地方放心使用。

三、Provider

1. Provider的理解

Provider是有必要單獨提出來一節(jié)的,上面第二節(jié)中我們其實只是簡單的使用了其中一種的provider下面來詳細說一下Provider

在Angular中,Provider描述了注入器(Injector)如何初始化令牌(Token)所對應的依賴服務。Provider一個運行時的依賴,注入器依靠它來創(chuàng)建服務對象的實例。

比如我們上面用到的例子:

// ...
@Component({
  //...
  // 2. 在組件中配置注入器
  providers: [
    MyService
  ]
  //...
})

實際上它的完整形式應該是這樣的:

@Component({
  //...
  // 2. 在組件中配置注入器
  providers: [
    {provide: MyService, useClass: MyService}
  ]
  //...
})

所以說我們上面只使用了一種provider: 類Provider(ClassProvider)。

2. Provider注冊方式

上面提到我只使用了其中一種注冊方式,那么下面介紹Angular中提供的四中常見的注冊方式:

  1. 類Provider(ClassProvider)

  2. 值Provider(ValueProvider)

  3. 別名Provider(ExistingProvider)

  4. 工廠Provider(FactoryProvider)

1. 類Provider

類Provider 基于令牌(Token)指定依賴項,這種方式可是讓依賴被動態(tài)指定為其他不同的具體實現(xiàn),只要接口不變,對于使用方就是透明的。比如數(shù)據(jù)渲染服務(Render),Render服務對上層提供的接口是固定的,倒是底層的渲染方式可以不同:

```ts
var inject = Injector.resolveAndCreate([
  {provide: Render, useClass: DomRender}
  //{provide: Render, useClass: DomRender} // canvas 渲染方式
  //{provide: Render, useClass: DomRender} // 服務的想染方式
])

// 調用方不用做任何修改
class AppComponent {
  construtor(private render: Render) {}
}
```

2. 值Provider

由于依賴的對象并不一定都是類,也可以是字符串、常量、對象等其他數(shù)據(jù)類型的,這可以方便用在全局變量、系統(tǒng)相關參數(shù)配置場景中。在創(chuàng)建Provider對象的時候,只需要使用useValue就可以聲明一個值Provider

```ts
let freeMan = {
  freeJob: boolen;
  live: () => {return 'do something u cant do'}
};

@Component({
  // ...
  providers: [
    {provide: 'someone', useValue: freeMan}
  ]
})
```

3. 別名Provider

有了別名Provider,我們就可以在一個Provider中配置多個令牌(Token),其對于的對象指向同一個實例,從而實現(xiàn)了多個依賴、一個對象實例的作用:

  // ...
  providers: [
    {provider: Power1, useClass: PowerService},
    {provider: Power2, useClass: PowerService}
  ]
  // ...

仔細想想,這樣對嗎?

顯然是不對的,如果兩個都使用了useClass那么按照令牌,將會創(chuàng)建兩個不同的實例出來,那么應該怎么實現(xiàn)兩個令牌同一個實例呢?答案是使用useExistiong:

  // ...
  providers: [
    {provider: Power1, useClass: PowerService},
    {provider: Power2, useExisting: PowerService}
  ]
  // ...

4. 工廠Provider

工廠Provider允許我們根據(jù)不同的條件來實例化不同的服務,比如,我們在開發(fā)環(huán)境需要打印日志,但是在實際部署的時候可能并不需要打印這些東西,那么我們總不可能去找到整個應用中所有的console.log()這樣的方法吧,這個時候我們可以使用工廠provider來幫我們處理,我們只需要在工廠provider中設定一個條件,使其能夠根據(jù)條件返回實例化我們需要的服務就可以了。為了實現(xiàn)這樣的功能我們可以在根模塊中這樣注入:

```ts
// app.module.ts
@NgModule({
// ...
providers: [
  HeroService,
  ConsoleService,
  {
    provide: LoggerService, 
    useFactory: (consoleService) => {
      return new LoggerService(true, consoleService);
    },
    deps: [ConsoleService]
  }
],
bootstrap: [AppComponent]
})
export class AppModule { }

哦哦,那兩個服務是這樣寫的:

  // console.service.ts
  // ...
  export class ConsoleService {
    log(message) {
      console.log(`ConsoleService: ${message}`);
    }
  }

  // logger.service.ts
  // ...
  export class LoggerService {
    constructor(private enable: boolean, 
      consoleService: ConsoleService
    ) { }

    log(message: string) {
      if (this.enable) {
        console.log(`LoggerService: ${message}`);
      }
    }
  }

然后在組件構造函數(shù)中寫上需要的服務就好。

四、限定方式的依賴注入

想象一場景,你應用中的某個服務的provider被當做無效代碼刪掉了,那么你的應用可能就會出問題。還好這個問題早在設計的時候就已經(jīng)考慮到了,我們可以使用Angular提供的@Optional和@Host裝飾器來解決這個問題。

Optional可以兼容依賴不存在的情況,提高系統(tǒng)的健壯性;@Host可以限定查找規(guī)則,明確實例化的位置,避免一些莫名的共享對象問題。

@Optional

借助@Optional就可以實現(xiàn)可選注入:

// app.component.ts
// ...
import { Optional } from '@angular/core';
constructor(@Optional() private logger: LoggerService) {
  if (this.logger) {
    this.logger.log('i am choosed');
  }
}

像例子中的那樣只需要在宿主組件(Host Component)的構造函數(shù)中增加@Optional裝飾器即可。

需要注意的是,上面例子中的LoggerService并不是不存在,只是并沒有根據(jù)providers元數(shù)據(jù)中配置被實例化出來。

@Host

Angular中依賴查找的規(guī)則是按照注入器從當前組件向父組件查找,直到找到要注入的依賴位置,如果找不到就會報錯。我們可以使用Angular提供的@Host裝飾器來解決 這個問題。

宿主組件如果一個組件注入了依賴項,那么這個組件就是這個依賴的宿主組件;如果這個組件通過<ng-content>被嵌入到了父組件,那這個父組件就是這個依賴的宿主組件。

1、宿主組件是當前組件

我們給組件構造函數(shù)加上@Host裝飾器:

 // ...
 @Component({
   selector: 'parent',
   template: `
     <h2>這里是父組件</h2>
   `
 })
 constructor(
   @Host()
   logger: LoggerService) {}
   // 加上@Host之后會報錯,因為我們并沒有在這個組件中注入LoggerService

   // 但是我們可以加上@Optional來避免報錯
   //@Host()
   //@Optional()
   //logger: LoggerService) {}
 )

2、宿主組件是父組件

我們修改一下上面的組件為父組件:

 // parent.component.ts
 // ...
 @Component({
   selector: 'parent',
   template: `
     <h2>這里是父組件</h2>
     <ng-content></content>
   `
   // 在父組件中注入 LoggerService
   providers: [LoggerService] 
 })
 constructor() {}

增加一個子組件:

 // child.component.ts
 // ...
 @Component({
   selector: 'child',
   template: `
     <h2>這里是子組件</h2>
   `
 })
 constructor(
   @Host()
   @Optional()
   logger: LoggerService) 
 ){}

當然<parent>標簽中應該這樣寫:

 <parent>
   <child></child>
 </parent>

因為此時宿主組件是父組件,所以我們在父組件中注入LoggerService  Angular注入器會自動向上查找,找到ParentComponet中的配置,從而完成注入。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Angular中依賴注入怎么用”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián)建站,關注創(chuàng)新互聯(lián)網(wǎng)站建設公司行業(yè)資訊頻道,更多相關知識等著你來學習!

另外有需要云服務器可以了解下創(chuàng)新互聯(lián)建站aaarwkj.com,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。

本文名稱:Angular中依賴注入怎么用-創(chuàng)新互聯(lián)
文章URL:http://aaarwkj.com/article30/dgdspo.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設網(wǎng)站策劃、網(wǎng)站內鏈、軟件開發(fā)微信小程序、網(wǎng)站營銷

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運營
国产黄色三级电影在线| 亚洲成人大片免费在线观看| 日韩福利成人av在线| 护士一级特黄特色大片| 91九色视频官网在线观看| 最新91熟女九色地址| 18岁禁看网站在线看| 日韩精品一区二区视频在线| 精品久久久久久亚洲野狼| 在线欧美日韩一区二区三区| 成人黄色大片免费看| 少妇高潮喷水下面的水| 精品在欧美一区二区少妇| 国产H精品在线观看| 国产三级网站在线观看播放| 精品蜜桃臀91人少妇| 日本人妻内射一区二区| 欧美日韩国产一区二区的 | 国产一区二区黄色网页| 亚洲人成伊人久久成| 午夜福利激情视频在线| 国产精品久久电影观看| 免费观看毛片一区二区三区| 午夜精品久久99蜜桃| 亚洲精品国产熟女av| 欧美日韩一区二区高清在线| 国产美女高潮流白浆视频免费看| 日本加勒比高清在线播放| 麻豆国产原创av色哟哟| 精品久久久久久蜜臀av| 国内一级片内射免费视频观看| 肥臀大屁股av在线播放| 国产精品伊人久久综合网| 麻豆乱淫一区二区三爱免费| 久久国产精品久久国产精品| 国产高清剧情av网站| 国产黄色三级电影在线| 国产精品一区二区夜夜夜| 自偷自拍亚洲综合精品| 国产中文字幕一区二区在线观看| 久久av免费一区二区观看|