最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Angular依賴注入體系中的基本概念是什么

這篇文章主要介紹“Angular依賴注入體系中的基本概念是什么”,在日常操作中,相信很多人在Angular依賴注入體系中的基本概念是什么問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Angular依賴注入體系中的基本概念是什么”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

我們提供的服務(wù)有:成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、都江堰ssl等。為上千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的都江堰網(wǎng)站制作公司

Angular依賴注入體系中的基本概念是什么

依賴注入

既然要介紹 Angular 框架的依賴注入設(shè)計(jì),那么先鋪墊一下依賴注入的基本概念。我們常常會(huì)搞混依賴倒置原則(DIP)、控制反轉(zhuǎn)(IoC)、依賴注入(DI)這幾個(gè)概念,因此這里會(huì)先簡(jiǎn)單介紹一下。

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

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

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

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

  • 高層模塊不應(yīng)該依賴低層模塊,兩者都應(yīng)該依賴其抽象;

  • 抽象不應(yīng)該依賴細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴抽象。

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

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

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

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

  • 依賴注入:被動(dòng)的接收依賴對(duì)象

  • 依賴查找:主動(dòng)索取依賴的對(duì)象

(3) 依賴注入。

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

依賴倒置和控制反轉(zhuǎn)兩者相輔相成,常??梢砸黄鹗褂?,可有效地降低模塊間的耦合。

Angular 中的依賴注入

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

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

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

  • 應(yīng)用中所需的任何依賴,都必須使用該應(yīng)用的注入器來注冊(cè)一個(gè)提供者,以便注入器可以使用這個(gè)提供者來創(chuàng)建新實(shí)例

  • Angular 會(huì)在啟動(dòng)過程中,創(chuàng)建全應(yīng)用級(jí)注入器以及所需的其它注入器

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

Injector 注入器

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

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

export abstract class Injector {
  // 找不到依賴
  static THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;
  // NullInjector 是樹的頂部
  // 如果你在樹中向上走了很遠(yuǎn),以至于要在 NullInjector 中尋找服務(wù),那么將收到錯(cuò)誤消息,或者對(duì)于 @Optional(),返回 null
  static NULL: Injector = new NullInjector();

  // 根據(jù)提供的 Token 從 Injector 檢索實(shí)例
  abstract get(
    token: Type | AbstractType | InjectionToken,
    notFoundValue?: T,
    flags?: InjectFlags
  ): T;

  // 創(chuàng)建一個(gè)新的 Injector 實(shí)例,該實(shí)例提供一個(gè)或多個(gè)依賴項(xiàng)
  static create(options: {
    providers: StaticProvider[];
    parent?: Injector;
    name?: string;
  }): Injector;

  // ??defineInjectable 用于構(gòu)造一個(gè) InjectableDef
  // 它定義 DI 系統(tǒng)將如何構(gòu)造 Token,并且在哪些 Injector 中可用
  static ?prov = ??defineInjectable({
    token: Injector,
    providedIn: "any" as any,
    // ??inject 生成的指令:從當(dāng)前活動(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 也劃分為模塊和組件級(jí)別,可分別為組件和模塊提供依賴的具體實(shí)例。注入器是可繼承的,這意味著如果指定的注入器無法解析某個(gè)依賴,它就會(huì)請(qǐng)求父注入器來解析它,我們同樣可以從上面的創(chuàng)建注入器代碼中看到:

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

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

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

Provider 提供者

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

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

關(guān)于 DI 令牌:

  • 當(dāng)使用提供者配置注入器時(shí),就會(huì)把提供者和一個(gè) DI 令牌關(guān)聯(lián)起來;

  • 注入器維護(hù)一個(gè)內(nèi)部令牌-提供者的映射表,當(dāng)請(qǐng)求一個(gè)依賴項(xiàng)時(shí)就會(huì)引用它,令牌就是這個(gè)映射表的鍵。

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

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,以及一個(gè) token
  key: ReflectiveKey;
  // 可以返回由鍵表示的對(duì)象的實(shí)例的工廠函數(shù)
  resolvedFactories: ResolvedReflectiveFactory[];
  // 指示提供者是多提供者,還是常規(guī)提供者
  multiProvider: boolean;
}

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

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

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

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

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

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

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

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

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

到此,關(guān)于“Angular依賴注入體系中的基本概念是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!


分享標(biāo)題:Angular依賴注入體系中的基本概念是什么
文章URL:http://fisionsoft.com.cn/article/ijhcos.html