1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      Angular中依賴注入怎么用

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

      我們擁有十余年網(wǎng)頁設(shè)計和網(wǎng)站建設(shè)經(jīng)驗,從網(wǎng)站策劃到網(wǎng)站制作,我們的網(wǎng)頁設(shè)計師為您提供的解決方案。為企業(yè)提供成都網(wǎng)站建設(shè)、做網(wǎng)站、微信開發(fā)、小程序開發(fā)、手機網(wǎng)站制作設(shè)計、H5網(wǎng)站設(shè)計、等業(yè)務(wù)。無論您有什么樣的網(wǎng)站設(shè)計或者設(shè)計方案要求,我們都將富于創(chuàng)造性的提供專業(yè)設(shè)計服務(wù)并滿足您的需求。

      一、什么是依賴注入

      控制反轉(zhuǎn)(IoC)

      控制反轉(zhuǎn)的概念最早在2004年由Martin Fowler提出,是針對面向?qū)ο笤O(shè)計不斷復(fù)雜化而提出的一種設(shè)計原則,是利用面向?qū)ο缶幊谭▌t來降低應(yīng)用耦合的設(shè)計模式。

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

      依賴注入(Dependency Injection)

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

      假設(shè)我們有一個能做漢堡的設(shè)備(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)建對應(yī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) {}
        //...
      }

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

      1. 在組件中注入服務(wù)

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

      1. 通過import導(dǎo)入被依賴的對象服務(wù)

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

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

      例子來了:

      // app.component.ts
      //...
      // 1. 導(dǎo)入被依賴對象的服務(wù)
      import { MyService } from './my-service/my-service.service';
      
      @Component({
        //...
        // 2. 在組件中配置注入器
        providers: [
          MyService
        ]
        //...
      })
      
      export class AppComponent {
        // 3. 在構(gòu)造函數(shù)中聲明需要注入的依賴
        constructor(private myService: MyService) {}
      }

      2. 在服務(wù)中注入服務(wù)

      除了組件依賴服務(wù),服務(wù)間依的相互調(diào)用也很寒常見。例如我們想給我們的漢堡機器人加上一個計數(shù)器,來記錄它的生產(chǎn)狀況,但是計數(shù)器又依靠電源來工作,我們就可以用一個服務(wù)來實現(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裝飾器是非必須的,因為只有一個服務(wù)依賴其他服務(wù)的時候才必須需要使用@Injectable顯式裝飾,來表示這個服務(wù)需要依賴,所以我們的PowerService并不是必須加上@Injectable裝飾器的,可是,Angular官方推薦是否依賴其他服務(wù),都應(yīng)該使用@Injectable來裝飾服務(wù)。

      3. 在模塊中注入服務(wù)

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

      // 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應(yīng)用啟動的時候,它好首先加載這個模塊需要的所有依賴,,此時會生成一個全局的根注入器,由該依賴創(chuàng)建的依賴注入對象會再整個應(yīng)用中可見,并共享一個實例。

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

      下面說兩種特殊情況:

      假設(shè)在兩個模塊中使用同樣的Token注入了同一個服務(wù),并且這兩個模塊先后導(dǎo)入到了根組件中:

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

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

      還是假設(shè)兩個模塊同樣使用同一個Token注入了同一個服務(wù),但是BModule模塊是導(dǎo)入在AModule模塊中的:

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

      那么這種情況下兩個模塊使用的都是AModule中注入的服務(wù)??梢酝茢喑鲈诟K中注入的服務(wù)是擁有最高優(yōu)先級的,你可以在任何地方放心使用。

      三、Provider

      1. Provider的理解

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

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

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

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

      實際上它的完整形式應(yīng)該是這樣的:

      @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ù)渲染服務(wù)(Render),Render服務(wù)對上層提供的接口是固定的,倒是底層的渲染方式可以不同:

      ```ts
      var inject = Injector.resolveAndCreate([
        {provide: Render, useClass: DomRender}
        //{provide: Render, useClass: DomRender} // canvas 渲染方式
        //{provide: Render, useClass: DomRender} // 服務(wù)的想染方式
      ])
      
      // 調(diào)用方不用做任何修改
      class AppComponent {
        construtor(private render: Render) {}
      }
      ```

      2. 值Provider

      由于依賴的對象并不一定都是類,也可以是字符串、常量、對象等其他數(shù)據(jù)類型的,這可以方便用在全局變量、系統(tǒng)相關(guān)參數(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)建兩個不同的實例出來,那么應(yīng)該怎么實現(xiàn)兩個令牌同一個實例呢?答案是使用useExistiong:

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

      4. 工廠Provider

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

      哦哦,那兩個服務(wù)是這樣寫的:

        // 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}`);
            }
          }
        }

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

      四、限定方式的依賴注入

      想象一場景,你應(yīng)用中的某個服務(wù)的provider被當做無效代碼刪掉了,那么你的應(yīng)用可能就會出問題。還好這個問題早在設(shè)計的時候就已經(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)的構(gòu)造函數(shù)中增加@Optional裝飾器即可。

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

      @Host

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

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

      1、宿主組件是當前組件

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

       // ...
       @Component({
         selector: 'parent',
         template: `
           

      這里是父組件

         `  })  constructor(    @Host()    logger: LoggerService) {}    // 加上@Host之后會報錯,因為我們并沒有在這個組件中注入LoggerService    // 但是我們可以加上@Optional來避免報錯    //@Host()    //@Optional()    //logger: LoggerService) {}  )

      2、宿主組件是父組件

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

       // parent.component.ts
       // ...
       @Component({
         selector: 'parent',
         template: `
           

      這里是父組件

               `    // 在父組件中注入 LoggerService    providers: [LoggerService]   })  constructor() {}

      增加一個子組件:

       // child.component.ts
       // ...
       @Component({
         selector: 'child',
         template: `
           

      這里是子組件

         `  })  constructor(    @Host()    @Optional()    logger: LoggerService)   ){}

      當然標簽中應(yīng)該這樣寫:

       
         
       

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

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


      網(wǎng)站標題:Angular中依賴注入怎么用
      標題網(wǎng)址:http://ef60e0e.cn/article/pogihj.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        盱眙县| 汉川市| 宁陵县| 金山区| 桂平市| 临海市| 盐池县| 沁源县| 淳化县| 潞西市| 龙里县| 富蕴县| 长岛县| 政和县| 始兴县| 宝兴县| 西畴县| 高唐县| 蛟河市| 怀宁县| 东平县| 长顺县| 闽侯县| 商河县| 轮台县| 明水县| 宣化县| 昌吉市| 静安区| 明水县| 荆州市| 柳江县| 江陵县| 平武县| 曲周县| 甘孜| 双城市| 富平县| 昌黎县| 阿坝| 托克逊县|