成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

聊聊Angular 依賴注入體系中的基本概念

本篇文章帶大家聊聊Angular,介紹一下依賴注入的基本概念,希望對大家有所幫助!

聊聊Angular 依賴注入體系中的基本概念

作為“為大型前端項(xiàng)目”而設(shè)計的前端框架,Angular 其實(shí)有許多值得參考和學(xué)習(xí)的設(shè)計,本系列主要用于研究這些設(shè)計和功能的實(shí)現(xiàn)原理。本文主要圍繞 Angular 中的最大特點(diǎn)——依賴注入,首先來介紹一些 Angular 依賴注入體系中的基本概念。

依賴注入

既然要介紹 Angular 框架的依賴注入設(shè)計,那么先鋪墊一下依賴注入的基本概念。我們常常會搞混依賴倒置原則(DIP)、控制反轉(zhuǎn)(IoC)、依賴注入(DI)這幾個概念,因此這里會先簡單介紹一下。【相關(guān)教程推薦:《angular教程》】

依賴倒置原則、控制反轉(zhuǎn)、依賴注入

低耦合、高內(nèi)聚大概是每個系統(tǒng)的設(shè)計目標(biāo)之一,而為此產(chǎn)生了很多的設(shè)計模式和理念,其中便包括依賴倒置原則、控制反轉(zhuǎn)的設(shè)計思想。

(1) 依賴倒置原則(DIP)。

依賴倒置原則的原始定義為:

  • 高層模塊不應(yīng)該依賴低層模塊,兩者都應(yīng)該依賴其抽象;
  • 抽象不應(yīng)該依賴細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴抽象。

簡單說便是:模塊間不應(yīng)該直接依賴對方,應(yīng)該依賴一個抽象的規(guī)則(接口或者時抽象類)。

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

控制反轉(zhuǎn)的定義為:模塊間的依賴關(guān)系從程序內(nèi)部提到外部來實(shí)例化管理。即對象在被創(chuàng)建的時候,由一個調(diào)控系統(tǒng)內(nèi)所有對象的外界實(shí)體控制,并將其所依賴的對象的引用傳遞(注入)給它。

實(shí)現(xiàn)控制反轉(zhuǎn)主要有兩種方式:

  • 依賴注入:被動的接收依賴對象
  • 依賴查找:主動索取依賴的對象

(3) 依賴注入。

依賴注入,是控制反轉(zhuǎn)的最為常見的一種技術(shù)。

依賴倒置和控制反轉(zhuǎn)兩者相輔相成,常常可以一起使用,可有效地降低模塊間的耦合。

Angular 中的依賴注入

在 Angular 中,同樣使用了依賴注入的技術(shù),DI 框架會在實(shí)例化某個類時,向其提供這個類所聲明的依賴項(xiàng)(依賴項(xiàng):指當(dāng)類需要執(zhí)行其功能時,所需要的服務(wù)或?qū)ο螅?/p>

Angular 中的依賴注入基本上是圍繞著組件或者是模塊展開的,主要用于給新建的組件提供依賴。

Angular 中主要的依賴注入機(jī)制是注入器機(jī)制

  • 應(yīng)用中所需的任何依賴,都必須使用該應(yīng)用的注入器來注冊一個提供者,以便注入器可以使用這個提供者來創(chuàng)建新實(shí)例
  • Angular 會在啟動過程中,創(chuàng)建全應(yīng)用級注入器以及所需的其它注入器

這里面主要涉及兩個概念,分別是Injector 注入器Provider 提供商,我們來看看。

Injector 注入器

Injector 注入器用于創(chuàng)建依賴,會維護(hù)一個容器來管理這些依賴,并盡可能地復(fù)用它們。注入器會提供依賴的一個單例,并把這個單例對象注入到多個組件中。

顯然,作為一個用來創(chuàng)建、管理、維護(hù)依賴的容器,注入器的功能很簡單:創(chuàng)建依賴實(shí)例、獲取依賴實(shí)例、管理依賴實(shí)例。我們也可以從抽象類Injector的源碼中看出來:

export abstract class Injector {   // 找不到依賴   static THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;   // NullInjector 是樹的頂部   // 如果你在樹中向上走了很遠(yuǎn),以至于要在 NullInjector 中尋找服務(wù),那么將收到錯誤消息,或者對于 @Optional(),返回 null   static NULL: Injector = new NullInjector();    // 根據(jù)提供的 Token 從 Injector 檢索實(shí)例   abstract get<T>(     token: Type<T> | AbstractType<T> | InjectionToken<T>,     notFoundValue?: T,     flags?: InjectFlags   ): T;    // 創(chuàng)建一個新的 Injector 實(shí)例,該實(shí)例提供一個或多個依賴項(xiàng)   static create(options: {     providers: StaticProvider[];     parent?: Injector;     name?: string;   }): Injector;    // ??defineInjectable 用于構(gòu)造一個 InjectableDef   // 它定義 DI 系統(tǒng)將如何構(gòu)造 Token,并且在哪些 Injector 中可用   static ?prov = ??defineInjectable({     token: Injector,     providedIn: "any" as any,     // ??inject 生成的指令:從當(dāng)前活動的 Injector 注入 Token     factory: () => ??inject(INJECTOR),   });    static __NG_ELEMENT_ID__ = InjectorMarkers.Injector; }

也就是說,我們可以將需要共享的依賴實(shí)例添加到注入器中,并通過 Token 查詢和檢索注入器來獲取相應(yīng)的依賴實(shí)例。

需要注意的是,Angular 中的注入器是分層的,因此查找依賴的過程也是向上遍歷注入器樹的過程。

這是因?yàn)樵?Angular 中,應(yīng)用是以模塊的方式組織的,具體可以參考5.模塊化組織篇。一般來說,頁面的 DOM 是以html作為根節(jié)點(diǎn)的樹狀結(jié)構(gòu),以此為基礎(chǔ),Angular 應(yīng)用中的組件和模塊也是與之相伴的樹狀結(jié)構(gòu)。

而注入器服務(wù)于組件和模塊,同樣是掛載與模塊和組織上的樹狀結(jié)構(gòu)。因此,Injector 也劃分為模塊和組件級別,可分別為組件和模塊提供依賴的具體實(shí)例。注入器是可繼承的,這意味著如果指定的注入器無法解析某個依賴,它就會請求父注入器來解析它,我們同樣可以從上面的創(chuàng)建注入器代碼中看到:

// 創(chuàng)建一個新的 Injector 實(shí)例,可傳入 parent 父注入器 static create(options: {providers: StaticProvider[], parent?: Injector, name?: string}): Injector;

在某個注入器的范圍內(nèi),服務(wù)是單例的。也就是說,在指定的注入器中最多只有某個服務(wù)的最多一個實(shí)例。如果不希望在所有地方都使用該服務(wù)的同一個實(shí)例,則可以通過注冊多個注入器、并按照需要關(guān)聯(lián)到組件和模塊中的方式,來按需共享某個服務(wù)依賴的實(shí)例。

我們可以看到創(chuàng)建一個新的Injector實(shí)例時,傳入的參數(shù)包括Provider,這是因?yàn)?code>Injector不會直接創(chuàng)建依賴,而是通過Provider來完成的。每個注入器會維護(hù)一個提供者的列表,并根據(jù)組件或其它服務(wù)的需要,用它們來提供服務(wù)的實(shí)例。

Provider 提供者

Provider 提供者用來告訴注入器應(yīng)該如何獲取或創(chuàng)建依賴,要想讓注入器能夠創(chuàng)建服務(wù)(或提供其它類型的依賴),必須使用某個提供者配置好注入器。

一個提供者對象定義了如何獲取與 DI 令牌(token) 相關(guān)聯(lián)的可注入依賴,而注入器會使用這個提供者來創(chuàng)建它所依賴的那些類的實(shí)例。

關(guān)于 DI 令牌:

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

提供者的類型很多,從官方文檔中可以閱讀它們的具體定義:

export type Provider =   | TypeProvider   | ValueProvider   | ClassProvider   | ConstructorProvider   | ExistingProvider   | FactoryProvider   | any[];

提供者的解析過程如下:

function resolveReflectiveFactory(   provider: NormalizedProvider ): ResolvedReflectiveFactory {   let factoryFn: Function;   let resolvedDeps: ReflectiveDependency[];   if (provider.useClass) {     // 使用類來提供依賴     const useClass = resolveForwardRef(provider.useClass);     factoryFn = reflector.factory(useClass);     resolvedDeps = _dependenciesFor(useClass);   } else if (provider.useExisting) {     // 使用已有依賴     factoryFn = (aliasInstance: any) => aliasInstance;     // 從根據(jù) token 獲取具體的依賴     resolvedDeps = [       ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting)),     ];   } else if (provider.useFactory) {     // 使用工廠方法提供依賴     factoryFn = provider.useFactory;     resolvedDeps = constructDependencies(provider.useFactory, provider.deps);   } else {     // 使用提供者具體的值作為依賴     factoryFn = () => provider.useValue;     resolvedDeps = _EMPTY_LIST;   }   //   return new ResolvedReflectiveFactory(factoryFn, resolvedDeps); }

根據(jù)不同類型的提供者,通過解析之后,得到由注入器 Injector 使用的提供者的內(nèi)部解析表示形式:

export interface ResolvedReflectiveProvider {   // 鍵,包括系統(tǒng)范圍內(nèi)的唯一 id,以及一個 token   key: ReflectiveKey;   // 可以返回由鍵表示的對象的實(shí)例的工廠函數(shù)   resolvedFactories: ResolvedReflectiveFactory[];   // 指示提供者是多提供者,還是常規(guī)提供者   multiProvider: boolean; }

提供者可以是服務(wù)類ClassProvider本身,如果把服務(wù)類指定為提供者令牌,那么注入器的默認(rèn)行為是用new來實(shí)例化那個類。

Angular 中的依賴注入服務(wù)

在 Angular 中,服務(wù)就是一個帶有@Injectable裝飾器的類,它封裝了可以在應(yīng)用程序中復(fù)用的非 UI 邏輯和代碼。Angular 把組件和服務(wù)分開,是為了增進(jìn)模塊化程度和可復(fù)用性。

@Injectable標(biāo)記一個類,以確保編譯器將在注入類時生成必要的元數(shù)據(jù)(元數(shù)據(jù)在 Angular 中也是很重要的一部分),以創(chuàng)建類的依賴項(xiàng)。

@Injectable裝飾器的類會在編譯之后,得到 Angular 可注入對象:

// 根據(jù)其 Injectable 元數(shù)據(jù),編譯 Angular 可注入對象,并對結(jié)果進(jìn)行修補(bǔ) export function compileInjectable(type: Type<any>, srcMeta?: Injectable): void {   // 該編譯過程依賴 @angular/compiler   // 可參考編譯器中的 compileFactoryFunction compileInjectable 實(shí)現(xiàn) }

Angular 中可注入對象(InjectableDef)定義 DI 系統(tǒng)將如何構(gòu)造 token 令牌,以及在哪些注入器(如果有)中可用:

export interface ??InjectableDef<T> {   // 指定給定類型屬于特定注入器,包括 root/platform/any/null 以及特定的 NgModule   providedIn: InjectorType<any> | "root" | "platform" | "any" | null;   // 此定義所屬的令牌   token: unknown;   // 要執(zhí)行以創(chuàng)建可注入實(shí)例的工廠方法   factory: (t?: Type<any>) => T;   // 在沒有顯式注入器的情況下,存儲可注入實(shí)例的位置   value: T | undefined; }

使用@Injectable()providedIn時,優(yōu)化工具可以進(jìn)行 Tree-shaking 優(yōu)化,從而刪除應(yīng)用程序中未使用的服務(wù),以減小捆綁包尺寸。

總結(jié)

本文簡單介紹了在 Angular 依賴注入體系中比較關(guān)鍵的幾個概念,主要包括InjectorProviderInjectable

對于注入器、提供者和可注入服務(wù),我們可以簡單地這樣理解:

  • 注入器用于創(chuàng)建依賴,會維護(hù)一個容器來管理這些依賴,并盡可能地復(fù)用它們。

  • 一個注入器中的依賴服務(wù),只有一個實(shí)例。

  • 注入器需要使用提供者來管理依賴,并通過 token(DI 令牌)來進(jìn)行關(guān)聯(lián)。

  • 提供者用于高速注入器應(yīng)該如何獲取或創(chuàng)建依賴。

  • 可注入服務(wù)類會根據(jù)元數(shù)據(jù)編譯后,得到可注入對象,該對象可用于創(chuàng)建實(shí)例。

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
国内精品九九久久精品| 大炕上的肉体交换| 八区精品色欲人妻综合网| 被村长狂躁俩小时玉婷| 国产2021在线传媒麻豆| 50多岁岳不让我戴套| 老狼一区忘忧草欢迎您大豆| 国产丝袜无码一区二区三区视频| 狠狠爱无码一区二区三区| 日本少妇自慰高清喷浆| 日韩精品人妻系列无码专区免费| 国内精品乱码卡一卡2卡三卡新区 国内精品乱码卡一卡2卡三卡 | 91老熟女老女人国产老太毛多| www.成人av| 国产成人AV综合亚洲色欲美女| 国内精品久久久久精品| 老太婆BBW搡BBBB搡搡搡搡| 人妻免费久久久久久久了| 无码AV专区丝袜专区| 亚洲色成人网站WWW永久小说| 99RE8这里有精品热视频 | 国产午夜成人无码一区二区| 亚洲无人区码一二三码区别图片| 丰满熟妇大肉唇张开| 国产午夜精品理论片| 老司机久久一区二区三区| 人妻熟女一区二区AⅤ| 小浪货腿打开水真多真紧| 色欲人妻Av一二区二区三区| 人妻系列综合第一页| 午夜天堂AV天堂久久久| 中国熟妇毛多多裸交视频| 成人欧美一区二区三区| 精品粉嫩BBWBBZBBW| 欧美人与性囗牲恔配视频0| 无码午夜成人1000部免费视频| 一二三四在线视频社区3| 大学生被内谢粉嫩无套| 久艾草久久综合精品无码| 人妻丰满熟妇AV无码区APP| 亚洲AV无码片VR一区二区三区| 无码专区狠狠躁天天躁| 中文字幕无线码免费人妻| 日本另类ΑV欧美另类AⅤ| 久人人爽人人爽人人片AV| 山东中年夫妇大白天露脸自拍| 亚洲色婷婷综合开心网| 成熟人妻换╳╳╳╳Ⅹ| 久久精品国产亚洲AVAPP下载| 日韩乱码人妻无码中文字幕视频 | 欧美交性一级视频免费播放| 五月丁香伊人久久91视频| [中文] [3D全彩H漫]新来| 综合在线视频精品专区| EEUSS影院WWW在线观看| 草莓视频在线播放视频| 精品久久久无码中字| 日本午夜免费福利视频| 亚洲最刺激成人无码| 国产成人麻豆精品午夜福利在线| A亚洲VA欧美VA国产综合| 中文字幕无码中文字幕有码A| 国产精品久久久久秋霞鲁丝| 女局长白白嫩嫩大屁股| 亚洲AV高潮黄色毛片| 差差漫画在线观看登录页面弹窗 | 亚洲AV无码第一区二区三区| 锕锕锕锕锕锕锕好疼免费视频 | 唔嗯啊欧美一级作爱网站| A级毛片高清免费播放| 吃奶呻吟打开双腿做受视频 | 国产麻豆精品一区| 欧洲熟妇色XXXXX老妇| 亚洲人成线无码7777| 国产成人AV无码专区亚洲AV| 妺妺窝人体色444444大粗| 亚洲AV无码专区亚洲AV桃花桃| 成人亚洲色欲色一欲WWW| 蜜臀AV福利无码一二三| 日本JAPANESE猛男GAY| 一二三四在线观看免费高清视频| 国产日产欧美一区二区蜜桃| 久久久久人妻精品区一| 性高朝久久久久久久久久| 成人免费AⅤ视频一区二区| 麻豆国产丝袜白领秘书在线观看| 亚洲AV无码成人精品区| 多毛BGMBGMBGM胖在线| 欧美乱强伦XXXXX高潮| 麻豆成人传媒一区二区| 欧美极品少妇XXXXⅩO69| 野花日本大全免费观看3中文版| 国产精品久久久久久免费软件| 人妻AV无码系列一区二区三区| 中国西西大胆女人裸体艺术| 精品深夜av无码一区二区老年| 无码人妻精品一区二区蜜桃温柔乡| 成人免费无码H在线观看不卡| 妺妺窝人体色www免费看| 野花高清在线电影观看免费视频| 黑人双人RAPPER剧情介绍| 午夜福利国产成人无码GIF动图 | 中国猛少妇色XXXXX| 久久变态刺激另类SM按摩| 亚洲AVAV黄网站| 国产精品乱码久久久久久小说| 欧洲做爰XXXⅩ富婆视频| √BT天堂网WWW中文在线| 老师黑色双开真丝旗袍| 亚洲自偷自拍另类小说| 性一交一乱一性一在线观看| 八戒八戒手机在线高清观看WWW| 免费精品一区二区三区第35| 在线观看国产精选免费| 久久亚洲精品无码爱剪辑| 亚洲熟妇AⅤ无码一区二区| 精品欧美成人高清在线观看| 亚洲国产天堂久久综合226| 韩国三级HD中文字幕叫床| 亚洲AV无码乱码在线观看代蜜桃| 国产亚洲精品岁国产微拍精品| 性色av无码人妻少妇肥臀| 国产无遮挡又黄又爽奶头| 亚洲AV丰满熟妇一区| 黑人巨大VS苍井空| 亚洲国产精品久久艾草| ZLJZLJZLJ日本人| 欧美肥肥婆另类XXXX000| 99精品国产一区二区三区不卡| 女人与公拘交酡过程高清视频| A∨变态另类天堂无码专区| 女人被爽到呻吟GIF动态图 | 亚洲国产美女精品久久久| 国产在线精品无码AV不卡顿| 亚洲AV之男人的天堂| XX娇小嫩XX中国XX| 人人妻人人爽人人做夜欢视频九色 | 国产日产欧产精品精品APP| 亚洲AV无码成人精品区| 精品久久久久久无码免费| 亚洲中文字幕乱码AV波多JI| 乱中年女人伦视频国产| 99久久人妻无码中文字幕系列| 強暴強姦AV正片一区二| 成人午夜福利免费无码视频| 双胞胎一前一后夹心饼干年下| 51久久夜色精品国产水果派解说 | 80S国产成年女人毛片| 欧美日产国产精品| 成人A片产无码免费视频在线观看 成人A毛片免费全部播放 | 国产精品无卡毛片视频| 亚洲国产AⅤ成人精品无吗| 久久久久久精品免费看SSS| 50岁露脸老熟女88AV| 日本大学学校AAAAA| 国产精品国产三级国产专不| 亚洲AV中文无码乱人伦在线播放 | 国产午夜亚洲精品国产成人小说| 亚洲国产婷婷六月丁香| 美女裸体无遮挡永久免费观看网站| A级毛片免费观看网站| 少妇被躁C至高潮HD | 亚洲成AV人片在线观看橙子| 国99精品无码一区二区三区| 西西人体大胆WWW444| 亚洲裸男GAY自慰网站| 国产三级精品三级男人的天堂 | 特级毛片内射WWW无码| MATURETUBE熟女| 色老99久久九九爱精品| 国内精品视频一区二区三区八戒| 我的初苞被强开了| 精品少妇人妻AV免费久久洗澡| 236宅宅理论片免费| 舌头伸进去添的我好爽高视频| 插花弄玉小说荔枝很甜| 无码人妻精一区二区三区| 久久精品女人天堂AV麻| 亚洲欧洲综合有码无码| 女人的抉择全集免费播放| 丰满少妇张开双腿无码AV| 亚洲乱码一卡二卡四卡乱码新区| 哦┅┅快┅┅用力啊┅┅| 国产AV一区二区精品凹凸| 亚洲日韩激情无码一区| 欧美日韩精品成人网站二区A∨有| 国产成人精品综合在线观看 | 美国白人未成年RAPPER豆瓣| 成人午夜性A级毛片免费| 亚洲娇小与黑人巨大交| 欧美日韩一区二区三区自拍 | 超碰人人爽天天爽天天做| 亚洲AV无码专区电影在线观看| 欧美 亚洲 另类 丝袜 自拍| 国产精品久久久久永久免费看| 亚洲午夜理论片在线观看| 肉感饱满中年熟妇日本| 痉挛高潮喷水AV无码免费| 丁香花高清在线观看完整版| 亚洲日韩电影久久|