国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Angular框架解讀--依賴注入的引導過程

開發 前端
本文主要圍繞 Angular 中的最大特點——依賴注入,介紹 Angular 依賴注入在體系在應用引導過程中的的設計和實現。

 [[412840]]

作為“為大型前端項目”而設計的前端框架,Angular 其實有許多值得參考和學習的設計,本系列主要用于研究這些設計和功能的實現原理。本文主要圍繞 Angular 中的最大特點——依賴注入,介紹 Angular 依賴注入在體系在應用引導過程中的的設計和實現。

多級依賴注入中,介紹了模塊注入器和元素注入器兩種層次結構的注入器。那么,Angular 在引導過程中,又是如何初始化根模塊和入口組件的呢?

Angular 的引導過程

前面我們說到,Angular 應用在瀏覽器中引導時,會創建瀏覽器平臺,并引導根模塊:

  1. platformBrowserDynamic().bootstrapModule(AppModule); 

引導根模塊

根模塊 AppModule

在 Angular 中,每個應用有至少一個 Angular 模塊,根模塊就是你用來引導此應用的模塊,它通常命名為 AppModule。

當你使用 Angular CLI 命令 ng new 生成一個應用時,其默認的 AppModule 是這樣的:

  1. import { BrowserModule } from '@angular/platform-browser'
  2. import { NgModule } from '@angular/core'
  3.  
  4. import { AppComponent } from './app.component'
  5.  
  6. @NgModule({ 
  7.   declarations: [ 
  8.     AppComponent 
  9.   ], 
  10.   imports: [ 
  11.     BrowserModule 
  12.   ], 
  13.   providers: [], 
  14.   bootstrap: [AppComponent] 
  15. }) 
  16. export class AppModule { } 

引導根模塊的過程

我們來看看平臺層引導根模塊的過程中都做了些什么:

  1. @Injectable() 
  2. export class PlatformRef { 
  3.   ... 
  4.  
  5.   bootstrapModuleFactory<M>(moduleFactory: NgModuleFactory<M>, options?: BootstrapOptions): 
  6.       Promise<NgModuleRef<M>> { 
  7.     // 由于實例化模塊時,會需要創建一些提供者,所以這里需要在實例化模塊之前創建 NgZone 
  8.     // 因此,這里創建了一個僅包含新 NgZone 的微型父注入器,并將其作為父傳遞給 NgModuleFactory 
  9.     const ngZoneOption = options ? options.ngZone : undefined; 
  10.     const ngZoneEventCoalescing = (options && options.ngZoneEventCoalescing) || false
  11.     const ngZoneRunCoalescing = (options && options.ngZoneRunCoalescing) || false
  12.     const ngZone = getNgZone(ngZoneOption, {ngZoneEventCoalescing, ngZoneRunCoalescing}); 
  13.     const providers: StaticProvider[] = [{provide: NgZone, useValue: ngZone}]; 
  14.     // ApplicationRef 將在 Angular zone 之外創建 
  15.     return ngZone.run(() => { 
  16.       // 在 ngZone.run 中創建 ngZoneInjector,以便在 Angular zone 中創建所有實例化的服務 
  17.       const ngZoneInjector = Injector.create( 
  18.           {providers: providers, parent: this.injector, name: moduleFactory.moduleType.name}); 
  19.       const moduleRef = <InternalNgModuleRef<M>>moduleFactory.create(ngZoneInjector); 
  20.       const exceptionHandler: ErrorHandler|null = moduleRef.injector.get(ErrorHandler, null); 
  21.       if (!exceptionHandler) { 
  22.         throw new Error('No ErrorHandler. Is platform module (BrowserModule) included?'); 
  23.       } 
  24.       ... 
  25.       return _callAndReportToErrorHandler(exceptionHandler, ngZone!, () => { 
  26.         const initStatus: ApplicationInitStatus = moduleRef.injector.get(ApplicationInitStatus); 
  27.         initStatus.runInitializers(); 
  28.         return initStatus.donePromise.then(() => { 
  29.           ... 
  30.           // 引導模塊 
  31.           this._moduleDoBootstrap(moduleRef); 
  32.           return moduleRef; 
  33.         }); 
  34.       }); 
  35.     }); 
  36.   } 
  37.  
  38.   bootstrapModule<M>( 
  39.       moduleType: Type<M>, 
  40.       compilerOptions: (CompilerOptions&BootstrapOptions)| 
  41.       Array<CompilerOptions&BootstrapOptions> = []): Promise<NgModuleRef<M>> { 
  42.     const options = optionsReducer({}, compilerOptions); 
  43.     // 編譯并創建 @NgModule 的實例 
  44.     return compileNgModuleFactory(this.injector, options, moduleType) 
  45.         .then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options)); 
  46.   } 
  47.  
  48.   private _moduleDoBootstrap(moduleRef: InternalNgModuleRef<any>): void { 
  49.     const appRef = moduleRef.injector.get(ApplicationRef) as ApplicationRef; 
  50.     // 引導應用程序 
  51.     if (moduleRef._bootstrapComponents.length > 0) { 
  52.       // 在應用程序的根級別引導新組件 
  53.       moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f)); 
  54.     } else if (moduleRef.instance.ngDoBootstrap) { 
  55.       moduleRef.instance.ngDoBootstrap(appRef); 
  56.     } else { 
  57.       ... 
  58.     } 
  59.     this._modules.push(moduleRef); 
  60.   } 

根模塊引導時,除了編譯并創建 AppModule 的實例,還會創建 NgZone,關于 NgZone 的請參考。在編譯和創建 AppModule 的過程中,便會創建 ApplicationRef ,即 Angular 應用程序。

引導 Angular 應用程序

前面在引導根模塊過程中,創建了 Angular 應用程序之后,便會在應用程序的根級別引導新組件:

  1. // 在應用程序的根級別引導新組件 
  2. moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f)); 

我們來看看這個過程會發生什么。

應用程序 ApplicationRef

一個 Angular 應用程序,提供了以下的能力:

  1. @Injectable() 
  2. export class ApplicationRef { 
  3.   // 獲取已注冊到該應用程序的組件類型的列表 
  4.   public readonly componentTypes: Type<any>[] = []; 
  5.   // 獲取已注冊到該應用程序的組件的列表 
  6.   public readonly components: ComponentRef<any>[] = []; 
  7.   // 返回一個 Observable,指示應用程序何時穩定或不穩定 
  8.   // 如果在應用程序引導時,引導任何種類的周期性異步任務,則該應用程序將永遠不會穩定(例如輪詢過程) 
  9.   public readonly isStable!: Observable<boolean>; 
  10.  
  11.   constructor( 
  12.       private _zone: NgZone, private _injector: Injector, private _exceptionHandler: ErrorHandler, 
  13.       private _componentFactoryResolver: ComponentFactoryResolver, 
  14.       private _initStatus: ApplicationInitStatus) { 
  15.         // 創建時,主要進行兩件事: 
  16.         // 1. 宏任務結束后,檢測視圖是否需要更新。 
  17.         // 2. 在 Angular Zone 之外創建對 onStable 的預訂,以便在 Angular Zone 之外運行回調。 
  18.   } 
  19.   // 在應用程序的根級別引導新組件 
  20.   bootstrap<C>(componentOrFactory: ComponentFactory<C>|Type<C>, rootSelectorOrNode?: string|any): 
  21.       ComponentRef<C> {} 
  22.   // 調用此方法以顯式處理更改檢測及其副作用 
  23.   tick(): void {} 
  24.   // 關聯視圖,以便對其進行臟檢查,視圖銷毀后將自動分離 
  25.   attachView(viewRef: ViewRef): void {} 
  26.   // 再次從臟檢查中分離視圖 
  27.   detachView(viewRef: ViewRef): void {} 

那么,我們來看看 bootstrap() 過程中,Angular 都做了些什么。

在應用程序的根級別引導根組件

將新的根組件引導到應用程序中時,Angular 將指定的應用程序組件安裝到由 componentType 的選擇器標識的 DOM 元素上,并引導自動更改檢測以完成組件的初始化。

  1. @Injectable() 
  2. export class ApplicationRef { 
  3.   bootstrap<C>(componentOrFactory: ComponentFactory<C>|Type<C>, rootSelectorOrNode?: string|any): 
  4.       ComponentRef<C> { 
  5.     ... 
  6.     // 如果未與其他模塊綁定,則創建與當前模塊關聯的工廠 
  7.     const ngModule = 
  8.         isBoundToModule(componentFactory) ? undefined : this._injector.get(NgModuleRef); 
  9.     const selectorOrNode = rootSelectorOrNode || componentFactory.selector; 
  10.     // 創建組件 
  11.     const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule); 
  12.     const nativeElement = compRef.location.nativeElement; 
  13.     // 創建可測試服務掛鉤 
  14.     const testability = compRef.injector.get(Testability, null); 
  15.     const testabilityRegistry = testability && compRef.injector.get(TestabilityRegistry); 
  16.     if (testability && testabilityRegistry) { 
  17.       testabilityRegistry.registerApplication(nativeElement, testability); 
  18.     } 
  19.     // 組件銷毀時,銷毀關聯視圖以及相關的服務 
  20.     compRef.onDestroy(() => { 
  21.       this.detachView(compRef.hostView); 
  22.       remove(this.components, compRef); 
  23.       if (testabilityRegistry) { 
  24.         testabilityRegistry.unregisterApplication(nativeElement); 
  25.       } 
  26.     }); 
  27.     // 加載組件,包括關聯視圖、監聽變更等 
  28.     this._loadComponent(compRef); 
  29.     ... 
  30.     return compRef; 
  31.   } 

在創建根組件的過程中,會關聯 DOM 元素視圖、添加對狀態變更的檢測機制。

根組件是一個入口組件,Angular CLI 創建的默認應用只有一個組件 AppComponent ,Angular 會在引導過程中把它加載到 DOM 中。

在根組件的創建過程中,通常會根據根組件中引用到的其他組件,觸發一系列組件的創建并形成組件樹。大多數應用只有一個組件樹,并且只從一個根組件開始引導。

創建組件過程

Angular 中創建組件的過程如下:

  1. 當 Angular 創建組件類的新實例時,它會通過查看該組件類的構造函數,來決定該組件依賴哪些服務或其它依賴項。
  2. 當 Angular 發現某個組件依賴某個服務時,它會首先檢查是否該注入器中已經有了那個服務的任何現有實例。如果所請求的服務尚不存在,注入器就會使用以前注冊的服務提供者來制作一個,并把它加入注入器中,然后把該服務返回給 Angular。
  3. 當所有請求的服務已解析并返回時,Angular 可以用這些服務實例為參數,調用該組件的構造函數。

Angular 會在執行應用時創建注入器,第一個注入器是根注入器,創建于引導過程中。借助注入器繼承機制,可以把全應用級的服務注入到這些組件中。

到這里,Angular 分別完成了根模塊、根組件和組件樹的引導過程,通過編譯器則可以將組件和視圖渲染到頁面上。

總結

在應用程序的引導過程中,Angular 采取了以下步驟來加載我們的第一個視圖:

  1. index.html 
  2. Main.ts 

本文我們重點從根模塊的引導過程開始,介紹了引導 Angular 應用程序、引導根組件、組件的創建等過程。至于組件樹的創建和渲染,則可以參考 編譯器 相關的內容。

 

責任編輯:張燕妮 來源: Here. There.
相關推薦

2014-07-08 14:05:48

DaggerAndroid依賴

2009-05-21 16:41:22

GuiceJava依賴注入

2023-10-07 08:35:07

依賴注入Spring

2025-01-02 00:00:00

2022-12-29 08:54:53

依賴注入JavaScript

2015-06-17 16:01:30

ASP.NET

2023-06-28 08:16:50

Autofac應用程序

2015-09-02 11:22:36

JavaScript實現思路

2011-05-31 10:00:21

Android Spring 依賴注入

2011-03-29 09:51:58

GuiceIOC

2019-12-20 14:19:47

Linux操作系統引導

2023-07-11 09:14:12

Beanquarkus

2022-04-11 09:02:18

Swift依賴注

2024-05-27 00:13:27

Go語言框架

2017-08-16 16:00:05

PHPcontainer依賴注入

2024-12-30 12:00:00

.NET Core依賴注入屬性注入

2009-10-09 17:51:15

RHEL引導故障

2009-12-10 19:02:30

2024-02-04 09:08:00

Autofac容器.NET

2024-01-02 08:22:01

Koin框架項目
點贊
收藏

51CTO技術棧公眾號

久久黄色级2电影| 一区二区三区在线播放欧美| 国产一区二区三区播放| 最新成人av网站| 热re91久久精品国99热蜜臀| 99热播精品免费| 日韩视频123| 男人天堂亚洲二区| 亚洲成人在线免费| 黄网址在线播放免费| 日本一区免费视频| 欧美精品无码一区二区三区| 国产成人av电影在线播放| 相泽南亚洲一区二区在线播放 | 国产成人亚洲精品青草天美| 美乳视频一区二区| 中文国产一区| 国产日韩欧美一区二区三区四区| 四季av一区二区凹凸精品| 国产99久久精品一区二区永久免费 | 亚洲国产精品久久久男人的天堂| 久草在在线视频| 久久综合色播五月| 亚洲成熟丰满熟妇高潮xxxxx| 99热这里都是精品| 青青在线视频免费| 国产精品福利一区二区三区| 一区二区三区免费播放| 中文字幕国产一区二区| 成年人视频在线网站| 亚洲成人精品影院| 国产鲁鲁视频在线观看免费| 欧美日韩一区二区三区视频| 欧美人与动牲性行为| 一本大道亚洲视频| 成人在线tv视频| 国产精选久久久久久| 国内精品福利| 国产三级中文字幕| 久久综合九色综合久久久精品综合| 无码无遮挡又大又爽又黄的视频| 1区2区3区精品视频| 欧美成人免费| 欧美精品一区二区三区四区| 伊人久久大香| 国产精品久久综合av爱欲tv| 亚洲一级二级| 18视频在线观看娇喘| 久久午夜色播影院免费高清 | 日韩成人xxxx| 日韩激情电影| 欧美精品在线免费观看| 国产精品嫩草影院在线看| 国产精品日韩一区二区| 精品无人码麻豆乱码1区2区| 无码少妇一区二区三区芒果| 亚洲成人动漫av| 人交獸av完整版在线观看| 久久精品国产精品亚洲| 日韩欧美不卡| 国产高清精品软男同| 国产精品久久久久久久午夜片| 性欧美精品孕妇| 日韩精品中文字幕在线不卡尤物 | 超碰96在线| 婷婷丁香久久五月婷婷| 中文在线观看免费| 久久久国产在线视频| 久久国产精品成人免费观看的软件| 国产美女99p| 不卡视频在线看| 亚洲成av人影片在线观看| 亚洲精品www久久久| 丝袜久久网站| 亚洲精品中字| 亚洲午夜一区二区三区| 香蕉视频亚洲一级| 91精品在线观| 成人动漫av在线| 国产午夜在线观看| 97caopron在线视频| 免费日韩av片| 午夜国产一区二区三区| 欧美一三区三区四区免费在线看 | 成人做爰视频www| 国产精品欧美在线| 精品一区二区日韩| 天堂中文在线资| 国产精品欧美在线观看| 国内av一区二区三区| 欧美一区午夜精品| 久久久加勒比| 极品日韩久久| 亚洲欧美另类小说视频| 亚洲少妇视频| 国产精品一区二区av| 国产精品天天摸av网| bl在线肉h视频大尺度| 国产日本欧美一区二区三区| 精品一区二区在线免费观看| 丝袜美女写真福利视频| 日韩在线免费高清视频| 一本不卡影院| 97影视大全免费追剧大全在线观看| 日韩黄色在线免费观看| 一区二区三区在线电影| 另类小说第一页| 亚洲视频在线视频| 日韩视频二区| 亚洲欧美一区二区三区在线播放| www.午夜精品| 麻豆成人综合网| 日本精品在线| 91久久久久久| 亚洲一区影音先锋| 在线日韩成人| 国产不卡一区二区视频| 亚洲成人中文字幕| 激情91久久| 一级片在线视频| 国产成人综合av| 国产精品久久久久久福利一牛影视| 日韩大片免费观看| 欧美日韩精品免费观看| 日韩欧美第一页| 久久国产亚洲| 欧美大片免费看| 精品日本一线二线三线不卡| 精品一区二区三区免费视频| 成年网站在线免费观看| 亚洲视频在线视频| 精品亚洲成a人| 不卡的av影片| 免费亚洲一区二区| 欧美精品123区| 精品99视频| 免费看美女视频在线网站| 99在线视频播放| 欧美亚洲综合色| 尹人成人综合网| 日本综合在线| 久久久久久久有限公司| 7777精品伊人久久久大香线蕉经典版下载 | 日本高清网站| 日本韩国在线不卡| 亚洲色图欧美激情| 九九久久精品| 桃花色综合影院| 国产高清自拍一区| 日韩视频一区在线观看| 精品一区二区三区在线播放| 男人的天堂免费在线视频| 国产日韩欧美大片| 久久国产精品电影| 亚洲色图一区二区三区| 91久久高清国语自产拍| 麻豆影院在线观看| 特级黄色录像片| 欧美精品在线免费播放| 亚洲黄一区二区三区| 黄p免费网站| 欧美69xxx| 日本视频二区| 国产男女无遮挡| 性欧美videoshd高清| 国产美女精品视频| 在线中文字幕不卡| 免费国产自线拍一欧美视频| 91福利在线尤物| 欧美国产亚洲一区| 日韩女在线观看| 欧美日韩一级片网站| 国产一区二区三区免费播放| 美国十次综合久久| 亚洲kkk444kkk在线观看| 久精品国产欧美| 在线观看欧美日韩| 亚洲色图20p| 久久婷婷影院| av日韩精品| 欧美尤物美女在线| 国产aaa一级片| 国产精品久久精品视| 亚洲人成伊人成综合网久久久| 国产精品久久一卡二卡| 亚洲视频碰碰| 小说区图片区亚洲| 视频二区在线| 国产免费裸体视频| 国产精品欧美亚洲777777 | 三上悠亚久久精品| 91久久嫩草影院一区二区| 亚洲精品ady| 一区二区三区四区蜜桃| 裸体一区二区| 日韩三级不卡| 伊人影院蕉久影院在线播放| 中文字幕永久视频| 日本欧美色综合网站免费| 97激碰免费视频|