亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

試讀angular源碼第一章:開(kāi)場(chǎng)與platformBrowserDynamic

RiverLi / 1159人閱讀

摘要:而且大部分人一聽(tīng)說(shuō)就會(huì)本能地避開(kāi)。至于啟動(dòng)項(xiàng)目,都是這一行開(kāi)始的。應(yīng)用是模塊化的,它擁有自己的模塊化系統(tǒng),稱(chēng)作。

開(kāi)場(chǎng)來(lái)個(gè)自我介紹

angular 源碼閱讀

項(xiàng)目地址

文章地址

angular 版本:8.0.0-rc.4

歡迎看看我的類(lèi)angular框架

關(guān)于為什么寫(xiě)這么一個(gè)項(xiàng)目

聲明:僅僅為個(gè)人閱讀源碼的理解,不一定完全正確,還需要大佬的指點(diǎn)。

其實(shí)市面上很多關(guān)于 vue和react 的源碼閱讀,但是基本上沒(méi)有看到關(guān)于 angular 系統(tǒng)性地源碼閱讀。

而且大部分人一聽(tīng)說(shuō) angular 就會(huì)本能地避開(kāi)。

但其實(shí)不是的,在我眼里 angular 只是套用了很多后端已有的概念,比如 DI,比如 AOT 等。

之前我寫(xiě)過(guò)一個(gè)類(lèi) angular 的框架 InDiv,基本上實(shí)現(xiàn)了大多數(shù) ng 的裝飾器。

而且在寫(xiě)這個(gè)項(xiàng)目的時(shí)候,我從 angular 上學(xué)到了很多。

這次,則希望通過(guò)閱讀 angular 的源代碼,學(xué)習(xí)到更多谷歌在設(shè)計(jì)模式上的運(yùn)用,學(xué)習(xí)到更多代碼優(yōu)化和結(jié)構(gòu)的運(yùn)用。

也有一點(diǎn)私心,希望更多人說(shuō) ng大法好 ,哈哈。

前提

希望看之前讀者能先了解一下 typescripy 和 angular 的基礎(chǔ)概念,因?yàn)槲恼吕飼?huì)出現(xiàn)大量的 DI,服務(wù)商啊這類(lèi)詞

    typescript

    angular文檔

項(xiàng)目結(jié)構(gòu)

項(xiàng)目下只有三個(gè)文件夾:angular docs 和 my-demo

- angular: 注釋版angular的ts源代碼
- docs: 文檔位置
- my-demo: 啟動(dòng)的一個(gè)demo項(xiàng)目

通過(guò) tsconfig 把 angular 別名設(shè)置到 angular這個(gè)文件夾,來(lái)閱讀下 ts 版本的源碼。

啟動(dòng)app

在瀏覽器端,每個(gè) angular app都是從 main.ts 開(kāi)始的。

import { enableProdMode } from "@angular/core";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";

import { AppModule } from "./app/app.module";
import { environment } from "./environments/environment";

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));

至于啟動(dòng)項(xiàng)目,都是這一行 platformBrowserDynamic().bootstrapModule(AppModule) 開(kāi)始的。

在 angular 的世界中,所有的app都是由 bootstrapModule 根模塊或主模塊啟動(dòng)的。

Angular 應(yīng)用是模塊化的,它擁有自己的模塊化系統(tǒng),稱(chēng)作 NgModule。

關(guān)于 NgModule

一個(gè) NgModule 就是一個(gè)容器,用于存放一些內(nèi)聚的代碼塊,這些代碼塊專(zhuān)注于某個(gè)應(yīng)用領(lǐng)域、某個(gè)工作流或一組緊密相關(guān)的功能。

它可以包含一些組件、服務(wù)提供商或其它代碼文件,其作用域由包含它們的 NgModule 定義。 它還可以導(dǎo)入一些由其它模塊中導(dǎo)出的功能,并導(dǎo)出一些指定的功能供其它 NgModule 使用。

每個(gè) Angular 應(yīng)用都至少有一個(gè) NgModule 類(lèi),也就是根模塊,它習(xí)慣上命名為 AppModule,并位于一個(gè)名叫 app.module.ts 的文件中。

引導(dǎo)這個(gè)根模塊就可以啟動(dòng)你的應(yīng)用。

當(dāng) bootstrap(引導(dǎo))根模塊之后,NgModule 會(huì)繼而實(shí)例化元數(shù)據(jù)中 bootstrap。

bootstrap 應(yīng)用的主視圖,稱(chēng)為根組件。它是應(yīng)用中所有其它視圖的宿主。只有根模塊才應(yīng)該設(shè)置這個(gè) bootstrap 屬性

platform

angular 抽象出 platform,來(lái)實(shí)現(xiàn)跨平臺(tái)。

實(shí)例化 angular 根模塊的 bootstrapModule 的方法在瀏覽器端來(lái)自 @angular/platform-browser-dynamic。

其實(shí)除了 @angular/platform-browser-dynamic 之外還有 @angular/platform-browser。

這兩個(gè)模塊的主要區(qū)別是編譯方式的不同, platform-browser-dynamic 提供 JIT 編譯,也就是說(shuō)編譯在瀏覽器內(nèi)完成,而 platform-browser 提供 AOT 編譯,編譯在本地完成。

至于區(qū)別

platformBrowserDynamic

angular/packages/platform-browser-dynamic/src/platform-browser-dynamic.ts

/**
 * @publicApi
 */
export const platformBrowserDynamic = createPlatformFactory(
    platformCoreDynamic, "browserDynamic", INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS);

platformBrowserDynamic 方法很簡(jiǎn)單,就是調(diào)用創(chuàng)建平臺(tái)的工廠方法 createPlatformFactory 返回的一個(gè)返回值是平臺(tái)實(shí)例 PlatformRef 的函數(shù)

createPlatformFactory

angular/packages/core/src/application_ref.ts

/**
 * Creates a factory for a platform
 *
 * @publicApi
 */
export function createPlatformFactory(
    parentPlatformFactory: ((extraProviders");

該方法接受三個(gè)參數(shù):

    parentPlatformFactory: ((extraProviders"); 返回父平臺(tái)工廠實(shí)例的方法

    name: string 平臺(tái)的名字

    providers: StaticProvider[] = [] DI的服務(wù)提供者

    首先通過(guò) InjectionToken 創(chuàng)建一個(gè) Platform: ${name} 的值提供商

    然后返回一個(gè)方法,接受服務(wù)提供者 extraProviders");,返回一個(gè)平臺(tái)實(shí)例 PlatformRef

createPlatformFactory 返回的方法

    獲取當(dāng)前平臺(tái)實(shí)例

    如果當(dāng)前平臺(tái)實(shí)例不存在并且不存在 AllowMultipleToken 這個(gè)允許多個(gè)令牌的服務(wù)提供者

      父級(jí)平臺(tái)工廠方法 parentPlatformFactory 存在,則合并服務(wù)提供商并遞歸調(diào)用 parentPlatformFactory

      父級(jí)平臺(tái)工廠方法 parentPlatformFactory 不存在,則使用注入器創(chuàng)建實(shí)例方法 Injector.create 創(chuàng)建實(shí)例平臺(tái)實(shí)例并用 createPlatform 設(shè)置為全局的平臺(tái)實(shí)例

    調(diào)用 assertPlatform 確認(rèn) IOC 容器中存在 該 marker 的平臺(tái)實(shí)例并返回

所以創(chuàng)建平臺(tái)實(shí)例的順序上,應(yīng)該是 合并 browserDynamic 的 provider => 合并 coreDynamic 的 provider => 合并 provider 并創(chuàng)建 core

大概用人話描述就是:

    判斷是否已經(jīng)創(chuàng)建過(guò)了

    判斷是否有父 Factory

    如果有父 Factory 就把調(diào)用 Factory 時(shí)傳入的 Provider 和調(diào)用 createPlatformFactory 傳入的 Provider 合并,然后調(diào)用父 Factory

    如果沒(méi)有父 Factory ,先創(chuàng)建一個(gè) Injector ,然后去創(chuàng)建 PlatformRef 實(shí)例

createPlatform

angular/packages/core/src/application_ref.ts

let _platform: PlatformRef;

/**
 * Creates a platform.
 * Platforms have to be eagerly created via this function.
 *
 * @publicApi
 */
export function createPlatform(injector: Injector): PlatformRef {
  if (_platform && !_platform.destroyed &&
      !_platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
    throw new Error(
        "There can be only one platform. Destroy the previous one to create a new one.");
  }
  _platform = injector.get(PlatformRef);
  const inits = injector.get(PLATFORM_INITIALIZER, null);
  if (inits) inits.forEach((init: any) => init());
  return _platform;
}

_platform 是全局的唯一平臺(tái)實(shí)例。

創(chuàng)建平臺(tái)實(shí)例關(guān)鍵方法,傳入服務(wù)注入器實(shí)例 injector 返回平臺(tái)實(shí)例:

    確認(rèn)全局的平臺(tái)實(shí)例存在,狀態(tài)不是被銷(xiāo)毀,并且不存在多個(gè)平臺(tái)實(shí)例

    從注入器中獲取平臺(tái)實(shí)例

    injector.get(PLATFORM_INITIALIZER, null) 獲取初始化平臺(tái)時(shí)需要執(zhí)行的函數(shù)并執(zhí)行

回過(guò)頭看 platformBrowserDynamic

angular/packages/platform-browser-dynamic/src/platform-browser-dynamic.ts

/**
 * @publicApi
 */
export const platformBrowserDynamic = createPlatformFactory(
    platformCoreDynamic, "browserDynamic", INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS);

重點(diǎn)來(lái)了:INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS

這個(gè) providers 究竟提供了什么服務(wù)?

angular/packages/platform-browser-dynamic/src/platform_providers.ts

/**
 * @publicApi
 */
export const INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS: StaticProvider[] = [
  INTERNAL_BROWSER_PLATFORM_PROVIDERS,
  {
    provide: COMPILER_OPTIONS,
    useValue: {providers: [{provide: ResourceLoader, useClass: ResourceLoaderImpl, deps: []}]},
    multi: true
  },
  {provide: PLATFORM_ID, useValue: PLATFORM_BROWSER_ID},
];

除了 COMPILER_OPTIONSPLATFORM_ID,大概重點(diǎn)就是 INTERNAL_BROWSER_PLATFORM_PROVIDERS 了吧。

INTERNAL_BROWSER_PLATFORM_PROVIDERS 來(lái)自 @angular/platform-browser

angular/packages/platform-browser/src/browser.ts

export const INTERNAL_BROWSER_PLATFORM_PROVIDERS: StaticProvider[] = [
  {provide: PLATFORM_ID, useValue: PLATFORM_BROWSER_ID},
  {provide: PLATFORM_INITIALIZER, useValue: initDomAdapter, multi: true},
  {provide: PlatformLocation, useClass: BrowserPlatformLocation, deps: [DOCUMENT]},
  {provide: DOCUMENT, useFactory: _document, deps: []},
];

@angular/platform-browser 提供了一些瀏覽器端的ng實(shí)現(xiàn):

    PLATFORM_INITIALIZER 是初始化需要執(zhí)行的方法集合 這個(gè)很重要

    DOCUMENT 瀏覽器端的 document ,_document 工廠方法返回 document

在上面,createPlatform 的時(shí)候,會(huì) const inits = injector.get(PLATFORM_INITIALIZER, null); if (inits) inits.forEach((init: any) => init()); 依次執(zhí)行 PLATFORM_INITIALIZER 注入的工廠方法。

那么來(lái)看看 initDomAdapter 吧:

angular/packages/platform-browser/src/browser.ts

export function initDomAdapter() {
  BrowserDomAdapter.makeCurrent();
  BrowserGetTestability.init();
}

    BrowserDomAdapter.makeCurrent(); 通過(guò) BrowserDomAdapter 的靜態(tài)方法實(shí)例化一個(gè) BrowserDomAdapter 全局DOM適配器 ,具體就是實(shí)現(xiàn)并封裝了一些在瀏覽器端的方法,具體的可以看 angular/packages/platform-browser/src/browser/browser_adapter.ts 中的 class BrowserDomAdapter extends GenericBrowserDomAdapter

    BrowserGetTestability.init(); 則是初始化 angular 的測(cè)試,這個(gè)就沒(méi)看了

回過(guò)頭看下,在創(chuàng)建 platformBrowserDynamic 時(shí)候,傳入了返回父平臺(tái)實(shí)例的方法 platformCoreDynamic

platformCoreDynamic

angular/packages/platform-browser-dynamic/src/platform_core_dynamic.ts

import {COMPILER_OPTIONS, CompilerFactory, PlatformRef, StaticProvider, createPlatformFactory, platformCore} from "@angular/core";
import {JitCompilerFactory} from "./compiler_factory";

/**
 * A platform that included corePlatform and the compiler.
 *
 * @publicApi
 */
export const platformCoreDynamic = createPlatformFactory(platformCore, "coreDynamic", [
  {provide: COMPILER_OPTIONS, useValue: {}, multi: true},
  {provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS]},
]);

platformCoreDynamic 又傳入了

    來(lái)自 @angular/core 的 平臺(tái)核心 platformCore

    平臺(tái)名 coreDynamic

    2個(gè)靜態(tài)服務(wù)提供者:編譯選項(xiàng) COMPILER_OPTIONSplatformDynamic 的JIT編譯器工廠 JitCompilerFactory

platformCore

angular/packages/core/src/platform_core_providers.ts

import {PlatformRef, createPlatformFactory} from "./application_ref";
import {PLATFORM_ID} from "./application_tokens";
import {Console} from "./console";
import {Injector, StaticProvider} from "./di";
import {TestabilityRegistry} from "./testability/testability";

const _CORE_PLATFORM_PROVIDERS: StaticProvider[] = [
  // Set a default platform name for platforms that don"t set it explicitly.
  {provide: PLATFORM_ID, useValue: "unknown"},
  // 在這里 PlatformRef 被加入了 injector 并在 createPlatformFactory 中實(shí)例化
  {provide: PlatformRef, deps: [Injector]},
  {provide: TestabilityRegistry, deps: []},
  {provide: Console, deps: []},
];

/**
 * This platform has to be included in any other platform
 *
 * @publicApi
 */
export const platformCore = createPlatformFactory(null, "core", _CORE_PLATFORM_PROVIDERS);

platformCore 則是創(chuàng)建了一個(gè)返回根平臺(tái)工廠實(shí)例的方法,并設(shè)置了4個(gè)基礎(chǔ)的DI的服務(wù)提供者

    PLATFORM_ID 平臺(tái)id

    PlatformRef 在這里 PlatformRef 被加入了 injector 并在后續(xù)的 createPlatformFactory 中通過(guò) createPlatform(Injector.create({providers: injectedProviders, name: desc})); 平臺(tái)實(shí)例會(huì)被實(shí)例化

    TestabilityRegistry 可測(cè)試性注冊(cè)表 測(cè)試相關(guān)

    Console 很有意思 angular 把 Console 作為服務(wù)注入了DI,但是 Console 只實(shí)現(xiàn)了 log和warn兩個(gè)方法

PlatformRef

angular/packages/core/src/application_ref.ts

@Injectable()
export class PlatformRef {
  private _modules: NgModuleRef<any>[] = [];
  private _destroyListeners: Function[] = [];
  private _destroyed: boolean = false;

  /** @internal */
  constructor(private _injector: Injector) {}

  bootstrapModuleFactory(moduleFactory: NgModuleFactory, options");Promise> {
        ...
  }

  bootstrapModule(
      moduleType: Type, compilerOptions: (CompilerOptions&BootstrapOptions)|
      Array = []): Promise> {
    const options = optionsReducer({}, compilerOptions);
    return compileNgModuleFactory(this.injector, options, moduleType)
        .then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options));
  }

  private _moduleDoBootstrap(moduleRef: InternalNgModuleRef<any>): void {
    ...
  }

  onDestroy(callback: () => void): void { this._destroyListeners.push(callback); }

  get injector(): Injector { return this._injector; }

  destroy() {
    if (this._destroyed) {
      throw new Error("The platform has already been destroyed!");
    }
    this._modules.slice().forEach(module => module.destroy());
    this._destroyListeners.forEach(listener => listener());
    this._destroyed = true;
  }

  get destroyed() { return this._destroyed; }
}

PlatformRef 就是平臺(tái)實(shí)例的類(lèi),有一些方法和屬性等,例如幾個(gè)關(guān)鍵的方法

    bootstrapModule 引導(dǎo)根模塊的方法

    bootstrapModuleFactory 實(shí)例模塊的工廠方法,會(huì)運(yùn)行 zone.js 并監(jiān)聽(tīng)事件

    destroy 銷(xiāo)毀平臺(tái)實(shí)例的方法

這個(gè)我們放到后文去說(shuō)吧

總結(jié)

調(diào)用 platformBrowserDynamic() 并生成平臺(tái)實(shí)例 PlatformRef 時(shí)大概經(jīng)歷了這些:

    調(diào)用 createPlatformFactory 合并平臺(tái) browserDynamicproviders 并觸發(fā)父級(jí)平臺(tái) coreDynamic 的平臺(tái)工廠函數(shù)

    調(diào)用 createPlatformFactory 合并平臺(tái) coreDynamicproviders 并觸發(fā)父級(jí)平臺(tái) core 的平臺(tái)工廠函數(shù)

    由于平臺(tái) core 無(wú)父級(jí)平臺(tái),調(diào)用 Injector.create 創(chuàng)建 PlatformRef 實(shí)例,并賦值給全局唯一的平臺(tái)實(shí)例 _platform

    createPlatform 創(chuàng)建 PlatformRef 的時(shí)候,實(shí)例化一個(gè) BrowserDomAdapter 全局DOM適配器 ,具體就是實(shí)現(xiàn)并封裝了一些在瀏覽器端的方法

    最后斷言,確認(rèn)存在 PlatformRef 實(shí)例,并返回 PlatformRef 實(shí)例

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/7881.html

相關(guān)文章

  • angular源碼分析之platformBrowserDynamic

    摘要:生成項(xiàng)目后,中的代碼這里調(diào)用了包中導(dǎo)出的函數(shù)這個(gè)函數(shù)是瀏覽器平臺(tái)的工廠函數(shù)執(zhí)行會(huì)返回瀏覽器平臺(tái)的實(shí)例函數(shù)是通過(guò)函數(shù)創(chuàng)建的這個(gè)函數(shù)接收個(gè)參數(shù)父平臺(tái)工廠函數(shù)平臺(tái)名稱(chēng)服務(wù)提供商的數(shù)組顧名思義函數(shù)的作用是創(chuàng)建平臺(tái)工廠的函數(shù)在框架被加 cli生成項(xiàng)目后,main.ts中的代碼 import { enableProdMode } from @angular/core; import { platf...

    FWHeart 評(píng)論0 收藏0
  • angular源碼分析之platformBrowserDynamic

    摘要:生成項(xiàng)目后,中的代碼這里調(diào)用了包中導(dǎo)出的函數(shù)這個(gè)函數(shù)是瀏覽器平臺(tái)的工廠函數(shù)執(zhí)行會(huì)返回瀏覽器平臺(tái)的實(shí)例函數(shù)是通過(guò)函數(shù)創(chuàng)建的這個(gè)函數(shù)接收個(gè)參數(shù)父平臺(tái)工廠函數(shù)平臺(tái)名稱(chēng)服務(wù)提供商的數(shù)組顧名思義函數(shù)的作用是創(chuàng)建平臺(tái)工廠的函數(shù)在框架被加 cli生成項(xiàng)目后,main.ts中的代碼 import { enableProdMode } from @angular/core; import { platf...

    zhoutao 評(píng)論0 收藏0
  • Angular 2.x 從0到1 (一)史上最簡(jiǎn)單的Angular2教程

    摘要:官方支持微軟出品,是的超集,是的強(qiáng)類(lèi)型版本作為首選編程語(yǔ)言,使得開(kāi)發(fā)腳本語(yǔ)言的一些問(wèn)題可以更早更方便的找到。第一個(gè)組件那么我們來(lái)為我們的增加一個(gè)吧,在命令行窗口輸入。引導(dǎo)過(guò)程通過(guò)在中引導(dǎo)來(lái)啟動(dòng)應(yīng)用。它們的核心就是。 第一節(jié):Angular 2.0 從0到1 (一)第二節(jié):Angular 2.0 從0到1 (二)第三節(jié):Angular 2.0 從0到1 (三) 第一章:認(rèn)識(shí)Angular...

    tuniutech 評(píng)論0 收藏0
  • 從安裝認(rèn)識(shí)Angular 2

    摘要:首先,要確認(rèn)安裝了,并且創(chuàng)建了目錄并執(zhí)行初始化。想必看見(jiàn)上面的那么多包會(huì)一臉懵逼,沒(méi)關(guān)系,我第一眼看見(jiàn)這些的那刻,和你現(xiàn)在的表情一樣,下面在適當(dāng)?shù)臅r(shí)候我會(huì)逐個(gè)解釋的,你只需要相信我上面的包都是跑所必須的,缺一不可。 關(guān)于介紹,只說(shuō)一句:Angular 2是一個(gè)強(qiáng)大、全面、龐大的MVVM框架。 安裝 安裝,也算是一個(gè)坎,因?yàn)槟阈枰惭b一大堆東西,卻不知道每個(gè)東西是做什么的,盡管有Angu...

    xietao3 評(píng)論0 收藏0
  • angular2初入眼簾之-多components協(xié)作

    摘要:我們使用了模式書(shū)寫(xiě),并引入了思想,這些以前只在里見(jiàn)到的設(shè)計(jì),現(xiàn)在里也有體現(xiàn),并且在本章中會(huì)著重講解多的協(xié)作。如果之前寫(xiě)過(guò),那對(duì)于這種書(shū)寫(xiě)方式一定無(wú)比熟悉。每次數(shù)據(jù)的變更,無(wú)論是還是,都將變化冒泡到,然后由再向下逐級(jí)推送各組件是否重繪。 前集回顧 在上一章里我們講了如何在angular2下開(kāi)發(fā)一個(gè)component(還沒(méi)做的趕緊去學(xué)吧)。我們使用了Unidirectional Data ...

    dreamans 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<