日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Angular 中的依赖注入link

發(fā)布時間:2025/3/21 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Angular 中的依赖注入link 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Angular 中的依賴注入link

依賴注入(DI)是一種重要的應用設(shè)計模式。 Angular 有自己的 DI 框架,在設(shè)計應用時常會用到它,以提升它們的開發(fā)效率和模塊化程度。

依賴,是當類需要執(zhí)行其功能時,所需要的服務或?qū)ο蟆?DI 是一種編碼模式,其中的類會從外部源中請求獲取依賴,而不是自己創(chuàng)建它們。

在 Angular 中,DI 框架會在實例化該類時向其提供這個類所聲明的依賴項。本指南介紹了 DI 在 Angular 中的工作原理,以及如何借助它來讓你的應用更靈活、高效、健壯,以及可測試、可維護。

你可以運行本章這個范例應用的現(xiàn)場演練?/?下載范例。

我們先看一下英雄指南中英雄管理特性的簡化版。這個簡化版不使用 DI,我們將逐步把它轉(zhuǎn)換成使用 DI 的。

src/app/heroes/heroes.component.ts

src/app/heroes/hero-list.component.ts

src/app/heroes/hero.ts

src/app/heroes/mock-heroes.ts

content_copyimport { Hero } from './hero';export const HEROES: Hero[] = [{ id: 11, isSecret: false, name: 'Dr Nice' },{ id: 12, isSecret: false, name: 'Narco' },{ id: 13, isSecret: false, name: 'Bombasto' },{ id: 14, isSecret: false, name: 'Celeritas' },{ id: 15, isSecret: false, name: 'Magneta' },{ id: 16, isSecret: false, name: 'RubberMan' },{ id: 17, isSecret: false, name: 'Dynama' },{ id: 18, isSecret: true, name: 'Dr IQ' },{ id: 19, isSecret: true, name: 'Magma' },{ id: 20, isSecret: true, name: 'Tornado' } ];

HeroesComponent?是頂級英雄管理組件。 它唯一的目的是顯示?HeroListComponent,該組件會顯示一個英雄名字的列表。

HeroListComponent?的這個版本從?HEROES?數(shù)組(它在一個獨立的?mock-heroes?文件中定義了一個內(nèi)存集合)中獲取英雄。

src/app/heroes/hero-list.component.ts (class)

content_copyexport class HeroListComponent {heroes = HEROES; }

這種方法在原型階段有用,但是不夠健壯、不利于維護。 一旦你想要測試該組件或想從遠程服務器獲得英雄列表,就不得不修改?HeroesListComponent?的實現(xiàn),并且替換每一處使用了?HEROES?模擬數(shù)據(jù)的地方。

創(chuàng)建和注冊可注入的服務

DI 框架讓你能從一個可注入的服務類(獨立文件)中為組件提供數(shù)據(jù)。為了演示,我們還會創(chuàng)建一個用來提供英雄列表的、可注入的服務類,并把它注冊為該服務的提供商。

在同一個文件中放多個類容易讓人困惑。我們通常建議你在單獨的文件中定義組件和服務。

如果你把組件和服務都放在同一個文件中,請務必先定義服務,然后再定義組件。如果在服務之前定義組件,則會在運行時收到一個空引用錯誤。

也可以借助?forwardRef()?方法來先定義組件,就像這個博客中解釋的那樣。

你還可以使用前向引用來打破循環(huán)依賴,參見?DI 一章中的例子。

創(chuàng)建可注入的服務類

Angular CLI?可以用下列命令在?src/app/heroes?目錄下生成一個新的?HeroService?類。

content_copyng generate service heroes/hero

下列命令會創(chuàng)建?HeroService?的骨架。

src/app/heroes/hero.service.ts (CLI-generated)

content_copyimport { Injectable } from '@angular/core';@Injectable({providedIn: 'root', }) export class HeroService {constructor() { } }

@Injectable()?是每個 Angular 服務定義中的基本要素。該類的其余部分導出了一個?getHeroes?方法,它會返回像以前一樣的模擬數(shù)據(jù)。(真實的應用可能會從遠程服務器中異步獲取這些數(shù)據(jù),不過這里我們先忽略它,專心實現(xiàn)服務的注入機制。)

src/app/heroes/hero.service.ts

content_copyimport { Injectable } from '@angular/core'; import { HEROES } from './mock-heroes';@Injectable({// we declare that this service should be created// by the root application injector.providedIn: 'root', }) export class HeroService {getHeroes() { return HEROES; } }

用服務提供商配置注入器

我們創(chuàng)建的類提供了一個服務。@Injectable()?裝飾器把它標記為可供注入的服務,不過在你使用該服務的?provider?提供商配置好 Angular 的依賴注入器之前,Angular 實際上無法將其注入到任何位置。

該注入器負責創(chuàng)建服務實例,并把它們注入到像?HeroListComponent?這樣的類中。 你很少需要自己創(chuàng)建 Angular 的注入器。Angular 會在執(zhí)行應用時為你創(chuàng)建注入器,第一個注入器是根注入器,創(chuàng)建于啟動過程中。

提供商會告訴注入器如何創(chuàng)建該服務。 要想讓注入器能夠創(chuàng)建服務(或提供其它類型的依賴),你必須使用某個提供商配置好注入器。

提供商可以是服務類本身,因此注入器可以使用?new?來創(chuàng)建實例。 你還可以定義多個類,以不同的方式提供同一個服務,并使用不同的提供商來配置不同的注入器。

注入器是可繼承的,這意味著如果指定的注入器無法解析某個依賴,它就會請求父注入器來解析它。 組件可以從它自己的注入器來獲取服務、從其祖先組件的注入器中獲取、從其父 NgModule 的注入器中獲取,或從?root?注入器中獲取。

  • 更多知識,參見?提供商的不同類型。

  • 更多知識,參見層次化注入器的工作原理。

你可以在三種位置之一設(shè)置元數(shù)據(jù),以便在應用的不同層級使用提供商來配置注入器:

  • 在服務本身的?@Injectable()?裝飾器中。

  • 在 NgModule 的?@NgModule()?裝飾器中。

  • 在組件的?@Component()?裝飾器中。

@Injectable()?裝飾器具有一個名叫?providedIn?的元數(shù)據(jù)選項,在那里你可以指定把被裝飾類的提供商放到?root?注入器中,或某個特定 NgModule 的注入器中。

@NgModule()?和?@Component()?裝飾器都有用一個?providers?元數(shù)據(jù)選項,在那里你可以配置 NgModule 級或組件級的注入器。

所有組件都是指令,而?providers?選項是從?@Directive()?中繼承來的。 你也可以與組件一樣的級別為指令、管道配置提供商。

欲知詳情,參見該在哪里配置提供商。

注入服務

HeroListComponent?要想從?HeroService?中獲取英雄列表,就得要求注入?HeroService,而不是自己使用?new?來創(chuàng)建自己的?HeroService?實例。

你可以通過制定帶有依賴類型的構(gòu)造函數(shù)參數(shù)來要求 Angular 在組件的構(gòu)造函數(shù)中注入依賴項。下面的代碼是?HeroListComponent?的構(gòu)造函數(shù),它要求注入?HeroService。

src/app/heroes/hero-list.component (constructor signature)

content_copyconstructor(heroService: HeroService)

當然,HeroListComponent?還應該使用注入的這個?HeroService?做一些事情。 這里是修改過的組件,它轉(zhuǎn)而使用注入的服務。與前一版本并列顯示,以便比較。

hero-list.component (with DI)

hero-list.component (without DI)

content_copyimport { Component } from '@angular/core'; import { Hero } from './hero'; import { HeroService } from './hero.service';@Component({selector: 'app-hero-list',template: `<div *ngFor="let hero of heroes">{{hero.id}} - {{hero.name}}</div>` }) export class HeroListComponent {heroes: Hero[];constructor(heroService: HeroService) {this.heroes = heroService.getHeroes();} }

必須在某些父注入器中提供?HeroService。HeroListComponent?并不關(guān)心?HeroService?來自哪里。 如果你決定在?AppModule?中提供?HeroService,也不必修改?HeroListComponent。

注入器樹與服務實例

在某個注入器的范圍內(nèi),服務是單例的。也就是說,在指定的注入器中最多只有某個服務的最多一個實例。

應用只有一個根注入器。在?root?或?AppModule?級提供?UserService?意味著它注冊到了根注入器上。 在整個應用中只有一個?UserService?實例,每個要求注入?UserService?的類都會得到這一個服務實例,除非你在子注入器中配置了另一個提供商。

Angular DI 具有分層注入體系,這意味著下級注入器也可以創(chuàng)建它們自己的服務實例。 Angular 會有規(guī)律的創(chuàng)建下級注入器。每當 Angular 創(chuàng)建一個在?@Component()?中指定了?providers?的組件實例時,它也會為該實例創(chuàng)建一個新的子注入器。 類似的,當在運行期間加載一個新的 NgModule 時,Angular 也可以為它創(chuàng)建一個擁有自己的提供商的注入器。

子模塊和組件注入器彼此獨立,并且會為所提供的服務分別創(chuàng)建自己的實例。當 Angular 銷毀 NgModule 或組件實例時,也會銷毀這些注入器以及注入器中的那些服務實例。

借助注入器繼承機制,你仍然可以把全應用級的服務注入到這些組件中。 組件的注入器是其父組件注入器的子節(jié)點,它會繼承所有的祖先注入器,其終點則是應用的根注入器。 Angular 可以注入該繼承譜系中任何一個注入器提供的服務。

比如,Angular 既可以把?HeroComponent?中提供的?HeroService?注入到?HeroListComponent,也可以注入?AppModule?中提供的?UserService。

測試帶有依賴的組件

基于依賴注入設(shè)計一個類,能讓它更易于測試。 要想高效的測試應用的各個部分,你所要做的一切就是把這些依賴列到構(gòu)造函數(shù)的參數(shù)表中而已。

比如,你可以使用一個可在測試期間操縱的模擬服務來創(chuàng)建新的?HeroListComponent。

src/app/test.component.ts

content_copyconst expectedHeroes = [{name: 'A'}, {name: 'B'}] const mockService = <HeroService> {getHeroes: () => expectedHeroes }it('should have heroes when HeroListComponent created', () => {// Pass the mock to the constructor as the Angular injector wouldconst component = new HeroListComponent(mockService);expect(component.heroes.length).toEqual(expectedHeroes.length); });

欲知詳情,參見測試一章。

那些需要其它服務的服務

服務還可以具有自己的依賴。HeroService?非常簡單,沒有自己的依賴。不過,如果你希望通過日志服務來報告這些活動,那么就可以使用同樣的構(gòu)造函數(shù)注入模式,添加一個構(gòu)造函數(shù)來接收一個?Logger?參數(shù)。

這是修改后的?HeroService,它注入了?Logger,我們把它和前一個版本的服務放在一起進行對比。

src/app/heroes/hero.service (v2)

src/app/heroes/hero.service (v1)

src/app/logger.service

content_copyimport { Injectable } from '@angular/core'; import { HEROES } from './mock-heroes'; import { Logger } from '../logger.service';@Injectable({providedIn: 'root', }) export class HeroService {constructor(private logger: Logger) { }getHeroes() {this.logger.log('Getting heroes ...');return HEROES;} }

該構(gòu)造函數(shù)請求注入一個?Logger?的實例,并把它保存在一個名叫?logger?的私有字段中。 當要求獲取英雄列表時,getHeroes()?方法就會記錄一條消息。

注意,雖然?Logger?服務沒有自己的依賴項,但是它同樣帶有?@Injectable()?裝飾器。實際上,@Injectable()?對所有服務都是必須的

當 Angular 創(chuàng)建一個構(gòu)造函數(shù)中有參數(shù)的類時,它會查找有關(guān)這些參數(shù)的類型,和供注入使用的元數(shù)據(jù),以便找到正確的服務。 如果 Angular 無法找到參數(shù)信息,它就會拋出一個錯誤。?只有當類具有某種裝飾器時,Angular 才能找到參數(shù)信息。?@Injectable()?裝飾器是所有服務類的標準裝飾器。

裝飾器是 TypeScript 強制要求的。當 TypeScript 把代碼轉(zhuǎn)譯成 JavaScript 時,一般會丟棄參數(shù)的類型信息。只有當類具有裝飾器,并且?tsconfig.json?中的編譯器選項?emitDecoratorMetadata?為?true?時,TypeScript 才會保留這些信息。CLI 所配置的?tsconfig.json?就帶有?emitDecoratorMetadata: true。

這意味著你有責任給所有服務類加上?@Injectable()。

依賴注入令牌

當使用提供商配置注入器時,就會把提供商和一個?DI 令牌關(guān)聯(lián)起來。 注入器維護一個內(nèi)部令牌-提供商的映射表,當請求一個依賴項時就會引用它。令牌就是這個映射表的鍵。

在簡單的例子中,依賴項的值是一個實例,而類的類型則充當鍵來查閱它。 通過把?HeroService?類型作為令牌,你可以直接從注入器中獲得一個?HeroService?實例。

src/app/injector.component.ts

content_copyheroService: HeroService;

當你編寫的構(gòu)造函數(shù)中需要注入基于類的依賴項時,其行為也類似。 當你使用?HeroService?類的類型來定義構(gòu)造函數(shù)參數(shù)時,Angular 就會知道要注入與?HeroService?類這個令牌相關(guān)的服務。

src/app/heroes/hero-list.component.ts

content_copyconstructor(heroService: HeroService)

很多依賴項的值都是通過類來提供的,但不是全部。擴展的?provide?對象讓你可以把多種不同種類的提供商和 DI 令牌關(guān)聯(lián)起來。

  • 欲知詳情,參見不同種類的提供商。

可選依賴

HeroService?需要一個記錄器,但是如果找不到它會怎么樣?

當組件或服務聲明某個依賴項時,該類的構(gòu)造函數(shù)會以參數(shù)的形式接收那個依賴項。 通過給這個參數(shù)加上?@Optional()?注解,你可以告訴 Angular,該依賴是可選的。

content_copyimport { Optional } from '@angular/core'; content_copyconstructor(@Optional() private logger: Logger) {if (this.logger) {this.logger.log(some_message);} }

當使用?@Optional()?時,你的代碼必須能正確處理 null 值。如果你沒有在任何地方注冊過 logger 提供商,那么注入器就會把?logger?的值設(shè)置為 null。

@Inject()?和?@Optional()?都是參數(shù)裝飾器。它們通過在需要依賴項的類的構(gòu)造函數(shù)上對參數(shù)進行注解,來改變 DI 框架提供依賴項的方式。

欲知詳情,參見多級注入器。

小結(jié)

本頁中你學到了 Angular 依賴注入的基礎(chǔ)知識。 你可以注冊多種提供商,并且知道了如何通過為構(gòu)造函數(shù)添加參數(shù)來請求所注入的對象(比如服務)。

在以下頁面中可以深入了解 Angular DI 體系的能力及高級特性:

  • 要深入了解嵌套注入器,參見多級依賴注入

  • 到?DI 令牌與提供商中學習更多知識。

  • 依賴注入實戰(zhàn)中講了一些你能用 DI 做的一些有意思的事。

總結(jié)

以上是生活随笔為你收集整理的Angular 中的依赖注入link的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 巨乳女教师的诱惑 | 做暧暧视频在线观看 | 涩涩涩999 | 久久久久久av无码免费看大片 | 亚洲首页 | 精品久久久视频 | 97人妻人人澡人人爽人人精品 | av无码久久久久久不卡网站 | 日韩欧美一区在线观看 | 黄色wwww | 91精彩视频| 欧美天天搞 | 日韩激情久久 | 黄色片高清 | 花房姑娘免费观看全集 | 超碰啪啪| 久久国产乱子伦免费精品 | 草草影院欧美 | 久久久精品国产免费爽爽爽 | 亚洲视频91 | 日本wwwxx| 永久免费精品影视网站 | 天堂中文av在线 | 黄色污小说 | 秋霞无码一区二区 | 在线观看a网站 | 精品欧美色视频网站在线观看 | 亚洲制服av| 欧美精品色 | 欧美有码在线 | 国产91精| 日韩精品一区二区免费视频 | 国产aaa大片 | 日韩成人在线视频观看 | 久久久久亚洲AV成人无码国产 | 奇米影视久久 | 91视频看 | 国产农村妇女精品 | 男生和女生差差视频 | 亚洲一区二区在线看 | 色牛av| 超碰成人网 | 波多野结衣调教 | 麻豆网址 | 亚洲奶汁xxxx哺乳期 | 国产一区二区三区福利 | 深夜成人福利 | av在线免费播放 | 人妻熟妇又伦精品视频a | 狠狠躁夜夜躁人爽 | 成人免费av在线 | 最新网址av| 久草网在线观看 | 日本国产在线 | 国产哺乳奶水91在线播放 | 一区二区三区四区欧美 | 法国性xxxx精品hd | 国产www性| 国产亚洲精久久久久久无码苍井空 | 超色视频 | 黄色生活毛片 | 天天操夜夜操 | 欧美特级视频 | 欧美高清hd19| 日本三级一区二区 | 国产一二三四在线 | 国产人与zoxxxx另类 | 精品国产一二三四区 | 五月婷婷欧美 | 超碰最新上传 | 五月婷网| 亚洲精品一区二区三区中文字幕 | 精品成人一区二区 | 国模小黎自慰gogo人体 | 动漫玉足吸乳羞免费网站玉足 | 无遮挡边吃摸边吃奶边做 | 欧美性生活视频 | 在线观看黄网址 | 国产东北真实交换多p免视频 | 久久午夜神器 | 欧美草比视频 | 国产91免费视频 | 91精品又粗又猛又爽 | 草草在线影院 | 韩国久久久 | 天天色天天射综合网 | 热99精品| 日韩欧美国产电影 | 天堂网一区二区三区 | 日本国产精品一区 | 天天射天天干天天 | 91精品国产综合久久香蕉 | 亚洲精品乱码久久久久久按摩观 | 手机在线看片福利 | 日本成人精品在线 | 在线看a级片 | 丝袜 中出 制服 人妻 美腿 | 高清日韩一区二区 | 日韩xxx高潮hd|