国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Inhaltsverzeichnis
Dekoratoren und Metadaten
Dekoratoren und Metadaten in Angular
總結(jié)
Heim Web-Frontend js-Tutorial Lassen Sie uns über Metadaten und Dekoratoren in Angular sprechen

Lassen Sie uns über Metadaten und Dekoratoren in Angular sprechen

Feb 28, 2022 am 11:10 AM
angular

Dieser Artikel setzt das Erlernen von Angular fort, führt Sie zum Verst?ndnis der Metadaten und Dekoratoren in Angular und erkl?rt kurz deren Verwendung. Ich hoffe, dass er für alle hilfreich ist!

Lassen Sie uns über Metadaten und Dekoratoren in Angular sprechen

Als Front-End-Framework, das ?für gro?e Front-End-Projekte“ entwickelt wurde, verfügt Angular tats?chlich über viele Designs, die es wert sind, erw?hnt und erlernt zu werden. Diese Serie wird haupts?chlich zum Studium der Implementierungsprinzipien dieser Designs und Funktionen verwendet. In diesem Artikel werden haupts?chlich Metadaten vorgestellt, die überall in Angular zu finden sind. [Empfohlene verwandte Tutorials: ?Angular-Tutorial“]

Dekoratoren sind das Kernkonzept bei der Entwicklung mit Angular. In Angular werden Dekoratoren verwendet, um Metadaten an Klassen oder Eigenschaften anzuh?ngen, damit Sie wissen, was diese Klassen oder Eigenschaften bedeuten und wie Sie mit ihnen umgehen.

Dekoratoren und Metadaten

Weder Dekoratoren noch Metadaten sind von Angular vorgeschlagene Konzepte. Werfen wir also zun?chst einen kurzen Blick darauf.

Metadaten

In einem g?ngigen Konzept sind Metadaten Daten, die Benutzerdaten beschreiben. Es fasst grundlegende Informationen zu den Daten zusammen und kann das Auffinden und Verwenden bestimmter Dateninstanzen erleichtern. Beispielsweise sind Autor, Erstellungsdatum, ?nderungsdatum und Dateigr??e Beispiele für sehr grundlegende Dokumentmetadaten.

Im Fall von Klassen werden Metadaten verwendet, um die Klasse zu dekorieren, um die Definition und das Verhalten der Klasse zu beschreiben, sodass das erwartete Verhalten der Klasse konfiguriert werden kann.

Decorator

Decorator ist eine Sprachfunktion von JavaScript und eine experimentelle Funktion in Stufe 2.

Dekoratoren sind Funktionen, die w?hrend der Definition einer Klasse, eines Klassenelements oder einer anderen JavaScript-Syntaxform aufgerufen werden.

Dekoratoren haben drei Hauptfunktionen:

  • k?nnen den zu dekorierenden Wert durch einen passenden Wert mit derselben Semantik ersetzen. (Ein Dekorateur kann beispielsweise eine Methode durch eine andere Methode, ein Feld durch ein anderes Feld, eine Klasse durch eine andere Klasse usw. ersetzen.)

  • Es ist m?glich, Metadaten mit dem ge?nderten Wert zu verknüpfen; diese Metadaten k?nnen extern gelesen und für die Metaprogrammierung und Selbstprüfung verwendet werden.

  • Der Zugriff auf den zu ?ndernden Wert kann über Metadaten erfolgen. Bei ?ffentlichen Werten erfolgt dies über den Wertnamen, bei privaten Werten erhalten sie Zugriffsfunktionen, die dann optional geteilt werden k?nnen.

Im Wesentlichen k?nnen Dekoratoren verwendet werden, um einen Wert zu metaprogrammieren und ihm Funktionalit?t hinzuzufügen, ohne sein ?u?eres Verhalten grundlegend zu ?ndern.

Weitere Inhalte finden Sie im tc39/proposal-decorators-Vorschlag.

Dekoratoren und Metadaten in Angular

Wenn wir Angular-Anwendungen entwickeln, seien es Komponenten, Anweisungen, Dienste, Module usw., müssen wir Dekoratoren verwenden, um sie zu definieren und zu entwickeln. Dekoratoren erscheinen unmittelbar vor einer Klassendefinition und werden verwendet, um zu deklarieren, dass die Klasse einen bestimmten Typ hat, und um für diesen Typ geeignete Metadaten bereitzustellen.

Zum Beispiel k?nnen wir die folgenden Dekoratoren verwenden, um Angular-Klassen zu deklarieren: @Component(), @Directive(), @Pipe(), @Injectable(), @NgModule(). @Component()@Directive()@Pipe()、@Injectable()、@NgModule()

使用裝飾器和元數(shù)據(jù)來改變類的行為

@Component()為例,該裝飾器的作用包括:

  • 將類標(biāo)記為 Angular 組件。

  • 提供可配置的元數(shù)據(jù),用來確定應(yīng)在運行時如何處理、實例化和使用該組件。

關(guān)于@Component()該如何使用可以參考,這里不多介紹。我們來看看這個裝飾器的定義:

// 提供 Angular 組件的配置元數(shù)據(jù)接口定義
// Angular 中,組件是指令的子集,始終與模板相關(guān)聯(lián)
export interface Component extends Directive {
  // changeDetection 用于此組件的變更檢測策略
  // 實例化組件時,Angular 將創(chuàng)建一個更改檢測器,該更改檢測器負(fù)責(zé)傳播組件的綁定。
  changeDetection?: ChangeDetectionStrategy;
  // 定義對其視圖 DOM 子對象可見的可注入對象的集合
  viewProviders?: Provider[];
  // 包含組件的模塊的模塊ID,該組件必須能夠解析模板和樣式的相對 URL
  moduleId?: string;
  ...
  // 模板和 CSS 樣式的封裝策略
  encapsulation?: ViewEncapsulation;
  // 覆蓋默認(rèn)的插值起始和終止定界符(`{{`和`}}`)
  interpolation?: [string, string];
}

// 組件裝飾器和元數(shù)據(jù)
export const Component: ComponentDecorator = makeDecorator(
    'Component',
    // 使用默認(rèn)的 CheckAlways 策略,在該策略中,更改檢測是自動進行的,直到明確停用為止。
    (c: Component = {}) => ({changeDetection: ChangeDetectionStrategy.Default, ...c}),
    Directive, undefined,
    (type: Type<any>, meta: Component) => SWITCH_COMPILE_COMPONENT(type, meta));

以上便是組件裝飾、組件元數(shù)據(jù)的定義,我們來看看裝飾器的創(chuàng)建過程。

裝飾器的創(chuàng)建過程

我們可以從源碼中找到,組件和指令的裝飾器都會通過makeDecorator()來產(chǎn)生:

export function makeDecorator<T>(
    name: string, props?: (...args: any[]) => any, parentClass?: any, // 裝飾器名字和屬性
    additionalProcessing?: (type: Type<T>) => void,
    typeFn?: (type: Type<T>, ...args: any[]) => void):
    {new (...args: any[]): any; (...args: any[]): any; (...args: any[]): (cls: any) => any;} {
  // noSideEffects 用于確認(rèn)閉包編譯器包裝的函數(shù)沒有副作用
  return noSideEffects(() => { 
    const metaCtor = makeMetadataCtor(props);
    // 裝飾器工廠
    function DecoratorFactory(
        this: unknown|typeof DecoratorFactory, ...args: any[]): (cls: Type<T>) => any {
      if (this instanceof DecoratorFactory) {
        // 賦值元數(shù)據(jù)
        metaCtor.call(this, ...args);
        return this as typeof DecoratorFactory;
      }
      // 創(chuàng)建裝飾器工廠
      const annotationInstance = new (DecoratorFactory as any)(...args);
      return function TypeDecorator(cls: Type<T>) {
        // 編譯類
        if (typeFn) typeFn(cls, ...args);
        // 使用 Object.defineProperty 很重要,因為它會創(chuàng)建不可枚舉的屬性,從而防止該屬性在子類化過程中被復(fù)制。
        const annotations = cls.hasOwnProperty(ANNOTATIONS) ?
            (cls as any)[ANNOTATIONS] :
            Object.defineProperty(cls, ANNOTATIONS, {value: []})[ANNOTATIONS];
        annotations.push(annotationInstance);
        // 特定邏輯的執(zhí)行
        if (additionalProcessing) additionalProcessing(cls);

        return cls;
      };
    }
    if (parentClass) {
      // 繼承父類
      DecoratorFactory.prototype = Object.create(parentClass.prototype);
    }
    DecoratorFactory.prototype.ngMetadataName = name;
    (DecoratorFactory as any).annotationCls = DecoratorFactory;
    return DecoratorFactory as any;
  });
}

在上面的例子中,我們通過makeDecorator()產(chǎn)生了一個用于定義組件的Component裝飾器工廠。當(dāng)使用@Component()創(chuàng)建組件時,Angular 會根據(jù)元數(shù)據(jù)來編譯組件。

根據(jù)裝飾器元數(shù)據(jù)編譯組件

Angular 會根據(jù)該裝飾器元數(shù)據(jù),來編譯 Angular 組件,然后將生成的組件定義(?cmp

????Verwenden Sie Dekoratoren und Metadaten, um das Verhalten einer Klasse zu ?ndern. ???????? Am Beispiel von @Component() umfassen die Funktionen dieses Dekorators: ????????Markieren Sie die Klasse als Winkelkomponenten. ????????Stellt konfigurierbare Metadaten bereit, die bestimmen, wie die Komponente zur Laufzeit verarbeitet, instanziiert und verwendet werden soll. ????????Informationen zur Verwendung von @Component() finden Sie unter ??, hier gibt es nicht viel Einführung. Werfen wir einen Blick auf die Definition dieses Dekorators: ??
export function compileComponent(type: Type<any>, metadata: Component): void {
  // 初始化 ngDevMode
  (typeof ngDevMode === &#39;undefined&#39; || ngDevMode) && initNgDevMode();
  let ngComponentDef: any = null;
  // 元數(shù)據(jù)可能具有需要解析的資源
  maybeQueueResolutionOfComponentResources(type, metadata);
  // 這里使用的功能與指令相同,因為這只是創(chuàng)建 ngFactoryDef 所需的元數(shù)據(jù)的子集
  addDirectiveFactoryDef(type, metadata);
  Object.defineProperty(type, NG_COMP_DEF, {
    get: () => {
      if (ngComponentDef === null) {
        const compiler = getCompilerFacade();
        // 根據(jù)元數(shù)據(jù)解析組件
        if (componentNeedsResolution(metadata)) {
          ...
          // 異常處理
        }
        ...
        // 創(chuàng)建編譯組件需要的完整元數(shù)據(jù)
        const templateUrl = metadata.templateUrl || `ng:///${type.name}/template.html`;
        const meta: R3ComponentMetadataFacade = {
          ...directiveMetadata(type, metadata),
          typeSourceSpan: compiler.createParseSourceSpan(&#39;Component&#39;, type.name, templateUrl),
          template: metadata.template || &#39;&#39;,
          preserveWhitespaces,
          styles: metadata.styles || EMPTY_ARRAY,
          animations: metadata.animations,
          directives: [],
          changeDetection: metadata.changeDetection,
          pipes: new Map(),
          encapsulation,
          interpolation: metadata.interpolation,
          viewProviders: metadata.viewProviders || null,
        };
        // 編譯過程需要計算深度,以便確認(rèn)編譯是否最終完成
        compilationDepth++;
        try {
          if (meta.usesInheritance) {
            addDirectiveDefToUndecoratedParents(type);
          }
          // 根據(jù)模板、環(huán)境和組件需要的元數(shù)據(jù),來編譯組件
          ngComponentDef = compiler.compileComponent(angularCoreEnv, templateUrl, meta);
        } finally {
          // 即使編譯失敗,也請確保減少編譯深度
          compilationDepth--;
        }
        if (compilationDepth === 0) {
          // 當(dāng)執(zhí)行 NgModule 裝飾器時,我們將模塊定義加入隊列,以便僅在所有聲明都已解析的情況下才將隊列出隊,并將其自身作為模塊作用域添加到其所有聲明中
          // 此調(diào)用運行檢查以查看隊列中的任何模塊是否可以出隊,并將范圍添加到它們的聲明中
          flushModuleScopingQueueAsMuchAsPossible();
        }
        // 如果組件編譯是異步的,則聲明該組件的 @NgModule 批注可以執(zhí)行并在組件類型上設(shè)置 ngSelectorScope 屬性
        // 這允許組件在完成編譯后,使用模塊中的 directiveDefs 對其自身進行修補
        if (hasSelectorScope(type)) {
          const scopes = transitiveScopesFor(type.ngSelectorScope);
          patchComponentDefWithScope(ngComponentDef, scopes);
        }
      }
      return ngComponentDef;
    },
    ...
  });
}
??Das Obige ist die Definition der Komponentendekoration und der Komponentenmetadaten. Werfen wir einen Blick auf den Erstellungsprozess des Dekorators. ????????Der Erstellungsprozess von Dekoratoren????????Wir k?nnen ihn aus dem Quellcode finden. Dekoratoren für Komponenten und Anweisungen werden über makeDecorator() generiert: ??
export class CompileMetadataResolver {
  private _nonNormalizedDirectiveCache =
      new Map<Type, {annotation: Directive, metadata: cpl.CompileDirectiveMetadata}>();
  // 使用 Map 的方式來保存
  private _directiveCache = new Map<Type, cpl.CompileDirectiveMetadata>(); 
  private _summaryCache = new Map<Type, cpl.CompileTypeSummary|null>();
  private _pipeCache = new Map<Type, cpl.CompilePipeMetadata>();
  private _ngModuleCache = new Map<Type, cpl.CompileNgModuleMetadata>();
  private _ngModuleOfTypes = new Map<Type, Type>();
  private _shallowModuleCache = new Map<Type, cpl.CompileShallowModuleMetadata>();

  constructor(
      private _config: CompilerConfig, private _htmlParser: HtmlParser,
      private _ngModuleResolver: NgModuleResolver, private _directiveResolver: DirectiveResolver,
      private _pipeResolver: PipeResolver, private _summaryResolver: SummaryResolver<any>,
      private _schemaRegistry: ElementSchemaRegistry,
      private _directiveNormalizer: DirectiveNormalizer, private _console: Console,
      private _staticSymbolCache: StaticSymbolCache, private _reflector: CompileReflector,
      private _errorCollector?: ErrorCollector) {}
  // 清除特定某個指令的元數(shù)據(jù)
  clearCacheFor(type: Type) {
    const dirMeta = this._directiveCache.get(type);
    this._directiveCache.delete(type);
    ...
  }
  // 清除所有元數(shù)據(jù)
  clearCache(): void {
    this._directiveCache.clear();
    ...
  }
  /**
   * 加載 NgModule 中,已聲明的指令和的管道
   */
  loadNgModuleDirectiveAndPipeMetadata(moduleType: any, isSync: boolean, throwIfNotFound = true):
      Promise<any> {
    const ngModule = this.getNgModuleMetadata(moduleType, throwIfNotFound);
    const loading: Promise<any>[] = [];
    if (ngModule) {
      ngModule.declaredDirectives.forEach((id) => {
        const promise = this.loadDirectiveMetadata(moduleType, id.reference, isSync);
        if (promise) {
          loading.push(promise);
        }
      });
      ngModule.declaredPipes.forEach((id) => this._loadPipeMetadata(id.reference));
    }
    return Promise.all(loading);
  }
  // 加載指令(組件)元數(shù)據(jù)
  loadDirectiveMetadata(ngModuleType: any, directiveType: any, isSync: boolean): SyncAsync<null> {
    // 若已加載,則直接返回
    if (this._directiveCache.has(directiveType)) {
      return null;
    }
    directiveType = resolveForwardRef(directiveType);
    const {annotation, metadata} = this.getNonNormalizedDirectiveMetadata(directiveType)!;
    // 創(chuàng)建指令(組件)元數(shù)據(jù)
    const createDirectiveMetadata = (templateMetadata: cpl.CompileTemplateMetadata|null) => {
      const normalizedDirMeta = new cpl.CompileDirectiveMetadata({
        isHost: false,
        type: metadata.type,
        isComponent: metadata.isComponent,
        selector: metadata.selector,
        exportAs: metadata.exportAs,
        changeDetection: metadata.changeDetection,
        inputs: metadata.inputs,
        outputs: metadata.outputs,
        hostListeners: metadata.hostListeners,
        hostProperties: metadata.hostProperties,
        hostAttributes: metadata.hostAttributes,
        providers: metadata.providers,
        viewProviders: metadata.viewProviders,
        queries: metadata.queries,
        guards: metadata.guards,
        viewQueries: metadata.viewQueries,
        entryComponents: metadata.entryComponents,
        componentViewType: metadata.componentViewType,
        rendererType: metadata.rendererType,
        componentFactory: metadata.componentFactory,
        template: templateMetadata
      });
      if (templateMetadata) {
        this.initComponentFactory(metadata.componentFactory!, templateMetadata.ngContentSelectors);
      }
      // 存儲完整的元數(shù)據(jù)信息,以及元數(shù)據(jù)摘要信息
      this._directiveCache.set(directiveType, normalizedDirMeta);
      this._summaryCache.set(directiveType, normalizedDirMeta.toSummary());
      return null;
    };

    if (metadata.isComponent) {
      // 如果是組件,該過程可能為異步過程,則需要等待異步過程結(jié)束后的模板返回
      const template = metadata.template !;
      const templateMeta = this._directiveNormalizer.normalizeTemplate({
        ngModuleType,
        componentType: directiveType,
        moduleUrl: this._reflector.componentModuleUrl(directiveType, annotation),
        encapsulation: template.encapsulation,
        template: template.template,
        templateUrl: template.templateUrl,
        styles: template.styles,
        styleUrls: template.styleUrls,
        animations: template.animations,
        interpolation: template.interpolation,
        preserveWhitespaces: template.preserveWhitespaces
      });
      if (isPromise(templateMeta) && isSync) {
        this._reportError(componentStillLoadingError(directiveType), directiveType);
        return null;
      }
      // 并將元數(shù)據(jù)進行存儲
      return SyncAsync.then(templateMeta, createDirectiveMetadata);
    } else {
      // 指令,直接存儲元數(shù)據(jù)
      createDirectiveMetadata(null);
      return null;
    }
  }
  // 獲取給定指令(組件)的元數(shù)據(jù)信息
  getDirectiveMetadata(directiveType: any): cpl.CompileDirectiveMetadata {
    const dirMeta = this._directiveCache.get(directiveType)!;
    ...
    return dirMeta;
  }
  // 獲取給定指令(組件)的元數(shù)據(jù)摘要信息
  getDirectiveSummary(dirType: any): cpl.CompileDirectiveSummary {
    const dirSummary =
        <cpl.CompileDirectiveSummary>this._loadSummary(dirType, cpl.CompileSummaryKind.Directive);
    ...
    return dirSummary;
  }
}
??Im obigen Beispiel: Wir verwenden makeDecorator(), um eine Component-Decorator-Factory zum Definieren von Komponenten zu generieren. Wenn Sie eine Komponente mit @Component() erstellen, kompiliert Angular die Komponente basierend auf den Metadaten. ????????Komponenten basierend auf Decorator-Metadaten kompilieren????????Angular kompiliert Angular-Komponenten basierend auf den Decorator-Metadaten und patcht dann die generierte Komponentendefinition (?cmp) auf den Komponententyp:??
export function compileComponent(type: Type<any>, metadata: Component): void {
  // 初始化 ngDevMode
  (typeof ngDevMode === &#39;undefined&#39; || ngDevMode) && initNgDevMode();
  let ngComponentDef: any = null;
  // 元數(shù)據(jù)可能具有需要解析的資源
  maybeQueueResolutionOfComponentResources(type, metadata);
  // 這里使用的功能與指令相同,因為這只是創(chuàng)建 ngFactoryDef 所需的元數(shù)據(jù)的子集
  addDirectiveFactoryDef(type, metadata);
  Object.defineProperty(type, NG_COMP_DEF, {
    get: () => {
      if (ngComponentDef === null) {
        const compiler = getCompilerFacade();
        // 根據(jù)元數(shù)據(jù)解析組件
        if (componentNeedsResolution(metadata)) {
          ...
          // 異常處理
        }
        ...
        // 創(chuàng)建編譯組件需要的完整元數(shù)據(jù)
        const templateUrl = metadata.templateUrl || `ng:///${type.name}/template.html`;
        const meta: R3ComponentMetadataFacade = {
          ...directiveMetadata(type, metadata),
          typeSourceSpan: compiler.createParseSourceSpan(&#39;Component&#39;, type.name, templateUrl),
          template: metadata.template || &#39;&#39;,
          preserveWhitespaces,
          styles: metadata.styles || EMPTY_ARRAY,
          animations: metadata.animations,
          directives: [],
          changeDetection: metadata.changeDetection,
          pipes: new Map(),
          encapsulation,
          interpolation: metadata.interpolation,
          viewProviders: metadata.viewProviders || null,
        };
        // 編譯過程需要計算深度,以便確認(rèn)編譯是否最終完成
        compilationDepth++;
        try {
          if (meta.usesInheritance) {
            addDirectiveDefToUndecoratedParents(type);
          }
          // 根據(jù)模板、環(huán)境和組件需要的元數(shù)據(jù),來編譯組件
          ngComponentDef = compiler.compileComponent(angularCoreEnv, templateUrl, meta);
        } finally {
          // 即使編譯失敗,也請確保減少編譯深度
          compilationDepth--;
        }
        if (compilationDepth === 0) {
          // 當(dāng)執(zhí)行 NgModule 裝飾器時,我們將模塊定義加入隊列,以便僅在所有聲明都已解析的情況下才將隊列出隊,并將其自身作為模塊作用域添加到其所有聲明中
          // 此調(diào)用運行檢查以查看隊列中的任何模塊是否可以出隊,并將范圍添加到它們的聲明中
          flushModuleScopingQueueAsMuchAsPossible();
        }
        // 如果組件編譯是異步的,則聲明該組件的 @NgModule 批注可以執(zhí)行并在組件類型上設(shè)置 ngSelectorScope 屬性
        // 這允許組件在完成編譯后,使用模塊中的 directiveDefs 對其自身進行修補
        if (hasSelectorScope(type)) {
          const scopes = transitiveScopesFor(type.ngSelectorScope);
          patchComponentDefWithScope(ngComponentDef, scopes);
        }
      }
      return ngComponentDef;
    },
    ...
  });
}

編譯組件的過程可能是異步的(比如需要解析組件模板或其他資源的 URL)。如果編譯不是立即進行的,compileComponent會將資源解析加入到全局隊列中,并且將無法返回?cmp,直到通過調(diào)用resolveComponentResources解決了全局隊列為止。

編譯過程中的元數(shù)據(jù)

元數(shù)據(jù)是有關(guān)類的信息,但它不是類的屬性。因此,用于配置類的定義和行為的這些數(shù)據(jù),不應(yīng)該存儲在該類的實例中,我們還需要在其他地方保存此數(shù)據(jù)。

在 Angular 中,編譯過程產(chǎn)生的元數(shù)據(jù),會使用CompileMetadataResolver來進行管理和維護,這里我們主要看指令(組件)相關(guān)的邏輯:

export class CompileMetadataResolver {
  private _nonNormalizedDirectiveCache =
      new Map<Type, {annotation: Directive, metadata: cpl.CompileDirectiveMetadata}>();
  // 使用 Map 的方式來保存
  private _directiveCache = new Map<Type, cpl.CompileDirectiveMetadata>(); 
  private _summaryCache = new Map<Type, cpl.CompileTypeSummary|null>();
  private _pipeCache = new Map<Type, cpl.CompilePipeMetadata>();
  private _ngModuleCache = new Map<Type, cpl.CompileNgModuleMetadata>();
  private _ngModuleOfTypes = new Map<Type, Type>();
  private _shallowModuleCache = new Map<Type, cpl.CompileShallowModuleMetadata>();

  constructor(
      private _config: CompilerConfig, private _htmlParser: HtmlParser,
      private _ngModuleResolver: NgModuleResolver, private _directiveResolver: DirectiveResolver,
      private _pipeResolver: PipeResolver, private _summaryResolver: SummaryResolver<any>,
      private _schemaRegistry: ElementSchemaRegistry,
      private _directiveNormalizer: DirectiveNormalizer, private _console: Console,
      private _staticSymbolCache: StaticSymbolCache, private _reflector: CompileReflector,
      private _errorCollector?: ErrorCollector) {}
  // 清除特定某個指令的元數(shù)據(jù)
  clearCacheFor(type: Type) {
    const dirMeta = this._directiveCache.get(type);
    this._directiveCache.delete(type);
    ...
  }
  // 清除所有元數(shù)據(jù)
  clearCache(): void {
    this._directiveCache.clear();
    ...
  }
  /**
   * 加載 NgModule 中,已聲明的指令和的管道
   */
  loadNgModuleDirectiveAndPipeMetadata(moduleType: any, isSync: boolean, throwIfNotFound = true):
      Promise<any> {
    const ngModule = this.getNgModuleMetadata(moduleType, throwIfNotFound);
    const loading: Promise<any>[] = [];
    if (ngModule) {
      ngModule.declaredDirectives.forEach((id) => {
        const promise = this.loadDirectiveMetadata(moduleType, id.reference, isSync);
        if (promise) {
          loading.push(promise);
        }
      });
      ngModule.declaredPipes.forEach((id) => this._loadPipeMetadata(id.reference));
    }
    return Promise.all(loading);
  }
  // 加載指令(組件)元數(shù)據(jù)
  loadDirectiveMetadata(ngModuleType: any, directiveType: any, isSync: boolean): SyncAsync<null> {
    // 若已加載,則直接返回
    if (this._directiveCache.has(directiveType)) {
      return null;
    }
    directiveType = resolveForwardRef(directiveType);
    const {annotation, metadata} = this.getNonNormalizedDirectiveMetadata(directiveType)!;
    // 創(chuàng)建指令(組件)元數(shù)據(jù)
    const createDirectiveMetadata = (templateMetadata: cpl.CompileTemplateMetadata|null) => {
      const normalizedDirMeta = new cpl.CompileDirectiveMetadata({
        isHost: false,
        type: metadata.type,
        isComponent: metadata.isComponent,
        selector: metadata.selector,
        exportAs: metadata.exportAs,
        changeDetection: metadata.changeDetection,
        inputs: metadata.inputs,
        outputs: metadata.outputs,
        hostListeners: metadata.hostListeners,
        hostProperties: metadata.hostProperties,
        hostAttributes: metadata.hostAttributes,
        providers: metadata.providers,
        viewProviders: metadata.viewProviders,
        queries: metadata.queries,
        guards: metadata.guards,
        viewQueries: metadata.viewQueries,
        entryComponents: metadata.entryComponents,
        componentViewType: metadata.componentViewType,
        rendererType: metadata.rendererType,
        componentFactory: metadata.componentFactory,
        template: templateMetadata
      });
      if (templateMetadata) {
        this.initComponentFactory(metadata.componentFactory!, templateMetadata.ngContentSelectors);
      }
      // 存儲完整的元數(shù)據(jù)信息,以及元數(shù)據(jù)摘要信息
      this._directiveCache.set(directiveType, normalizedDirMeta);
      this._summaryCache.set(directiveType, normalizedDirMeta.toSummary());
      return null;
    };

    if (metadata.isComponent) {
      // 如果是組件,該過程可能為異步過程,則需要等待異步過程結(jié)束后的模板返回
      const template = metadata.template !;
      const templateMeta = this._directiveNormalizer.normalizeTemplate({
        ngModuleType,
        componentType: directiveType,
        moduleUrl: this._reflector.componentModuleUrl(directiveType, annotation),
        encapsulation: template.encapsulation,
        template: template.template,
        templateUrl: template.templateUrl,
        styles: template.styles,
        styleUrls: template.styleUrls,
        animations: template.animations,
        interpolation: template.interpolation,
        preserveWhitespaces: template.preserveWhitespaces
      });
      if (isPromise(templateMeta) && isSync) {
        this._reportError(componentStillLoadingError(directiveType), directiveType);
        return null;
      }
      // 并將元數(shù)據(jù)進行存儲
      return SyncAsync.then(templateMeta, createDirectiveMetadata);
    } else {
      // 指令,直接存儲元數(shù)據(jù)
      createDirectiveMetadata(null);
      return null;
    }
  }
  // 獲取給定指令(組件)的元數(shù)據(jù)信息
  getDirectiveMetadata(directiveType: any): cpl.CompileDirectiveMetadata {
    const dirMeta = this._directiveCache.get(directiveType)!;
    ...
    return dirMeta;
  }
  // 獲取給定指令(組件)的元數(shù)據(jù)摘要信息
  getDirectiveSummary(dirType: any): cpl.CompileDirectiveSummary {
    const dirSummary =
        <cpl.CompileDirectiveSummary>this._loadSummary(dirType, cpl.CompileSummaryKind.Directive);
    ...
    return dirSummary;
  }
}

可以看到,在編譯過程中,不管是組件、指令、管道,還是模塊,這些類在編譯過程中的元數(shù)據(jù),都使用Map來存儲。

總結(jié)

本節(jié)我們介紹了 Angular 中的裝飾器和元數(shù)據(jù),其中元數(shù)據(jù)用于描述類的定義和行為。

在 Angular 編譯過程中,會使用Map的數(shù)據(jù)結(jié)構(gòu)來維護和存儲裝飾器的元數(shù)據(jù),并根據(jù)這些元數(shù)據(jù)信息來編譯組件、指令、管道和模塊等。

更多編程相關(guān)知識,請訪問:編程教學(xué)??!

Das obige ist der detaillierte Inhalt vonLassen Sie uns über Metadaten und Dekoratoren in Angular sprechen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erkl?rung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Hei?e KI -Werkzeuge

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem v?llig kostenlosen KI-Gesichtstausch-Tool aus!

Hei?e Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Hei?e Themen

PHP-Tutorial
1502
276
Metadaten-Scraping mit der New York Times API Metadaten-Scraping mit der New York Times API Sep 02, 2023 pm 10:13 PM

Einleitung Letzte Woche habe ich eine Einleitung über das Scrapen von Webseiten zum Sammeln von Metadaten geschrieben und erw?hnt, dass es unm?glich sei, die Website der New York Times zu scrapen. Die Paywall der New York Times blockiert Ihre Versuche, grundlegende Metadaten zu sammeln. Aber es gibt eine M?glichkeit, dieses Problem mithilfe der New York Times API zu l?sen. Vor kurzem habe ich mit dem Aufbau einer Community-Website auf der Yii-Plattform begonnen, die ich in einem zukünftigen Tutorial ver?ffentlichen werde. Ich m?chte in der Lage sein, problemlos Links hinzuzufügen, die für den Inhalt der Website relevant sind. W?hrend Benutzer URLs problemlos in Formulare einfügen k?nnen, ist die Bereitstellung von Titel- und Quelleninformationen zeitaufw?ndig. Deshalb werde ich im heutigen Tutorial den Scraping-Code, den ich kürzlich geschrieben habe, erweitern, um die New York Times-API zum Sammeln von Schlagzeilen zu nutzen, wenn ich einen Link zur New York Times hinzufüge. Denken Sie daran, ich bin involviert

So installieren Sie Angular unter Ubuntu 24.04 So installieren Sie Angular unter Ubuntu 24.04 Mar 23, 2024 pm 12:20 PM

Angular.js ist eine frei zug?ngliche JavaScript-Plattform zum Erstellen dynamischer Anwendungen. Es erm?glicht Ihnen, verschiedene Aspekte Ihrer Anwendung schnell und klar auszudrücken, indem Sie die Syntax von HTML als Vorlagensprache erweitern. Angular.js bietet eine Reihe von Tools, die Sie beim Schreiben, Aktualisieren und Testen Ihres Codes unterstützen. Darüber hinaus bietet es viele Funktionen wie Routing und Formularverwaltung. In dieser Anleitung wird erl?utert, wie Angular auf Ubuntu24 installiert wird. Zuerst müssen Sie Node.js installieren. Node.js ist eine JavaScript-Ausführungsumgebung, die auf der ChromeV8-Engine basiert und es Ihnen erm?glicht, JavaScript-Code auf der Serverseite auszuführen. In Ub sein

Eine kurze Analyse der Verwendung des Monaco-Editors in Angular Eine kurze Analyse der Verwendung des Monaco-Editors in Angular Oct 17, 2022 pm 08:04 PM

Wie verwende ich den Monaco-Editor in Angular? Der folgende Artikel dokumentiert die Verwendung des Monaco-Editors in Angular, der kürzlich in einem Unternehmen verwendet wurde. Ich hoffe, dass er für alle hilfreich sein wird!

Wie man PHP und Angular für die Frontend-Entwicklung verwendet Wie man PHP und Angular für die Frontend-Entwicklung verwendet May 11, 2023 pm 04:04 PM

Mit der rasanten Entwicklung des Internets wird auch die Front-End-Entwicklungstechnologie st?ndig verbessert und iteriert. PHP und Angular sind zwei Technologien, die in der Frontend-Entwicklung weit verbreitet sind. PHP ist eine serverseitige Skriptsprache, die Aufgaben wie die Verarbeitung von Formularen, die Generierung dynamischer Seiten und die Verwaltung von Zugriffsberechtigungen übernehmen kann. Angular ist ein JavaScript-Framework, mit dem Single-Page-Anwendungen entwickelt und komponentenbasierte Webanwendungen erstellt werden k?nnen. In diesem Artikel erfahren Sie, wie Sie PHP und Angular für die Frontend-Entwicklung verwenden und wie Sie diese kombinieren

Ein Artikel über serverseitiges Rendering (SSR) in Angular Ein Artikel über serverseitiges Rendering (SSR) in Angular Dec 27, 2022 pm 07:24 PM

Kennen Sie Angular Universal? Es kann dazu beitragen, dass die Website eine bessere SEO-Unterstützung bietet!

Greifen Sie mit Python auf Metadaten verschiedener Audio- und Videodateien zu Greifen Sie mit Python auf Metadaten verschiedener Audio- und Videodateien zu Sep 05, 2023 am 11:41 AM

Mit Mutagen und dem eyeD3-Modul in Python k?nnen wir auf die Metadaten von Audiodateien zugreifen. Für Videometadaten k?nnen wir Filme und die OpenCV-Bibliothek in Python verwenden. Metadaten sind Daten, die Informationen über andere Daten bereitstellen, beispielsweise Audio- und Videodaten. Zu den Metadaten für Audio- und Videodateien geh?ren Dateiformat, Dateiaufl?sung, Dateigr??e, Dauer, Bitrate usw. Durch den Zugriff auf diese Metadaten k?nnen wir Medien effizienter verwalten und die Metadaten analysieren, um nützliche Informationen zu erhalten. In diesem Artikel werfen wir einen Blick auf einige der von Python bereitgestellten Bibliotheken oder Module für den Zugriff auf Metadaten von Audio- und Videodateien. Auf Audio-Metadaten zugreifen Einige Bibliotheken für den Zugriff auf Audiodatei-Metadaten nutzen Mutagenese

Tokenbasierte Authentifizierung mit Angular und Node Tokenbasierte Authentifizierung mit Angular und Node Sep 01, 2023 pm 02:01 PM

Die Authentifizierung ist einer der wichtigsten Teile jeder Webanwendung. In diesem Tutorial werden tokenbasierte Authentifizierungssysteme und ihre Unterschiede zu herk?mmlichen Anmeldesystemen erl?utert. Am Ende dieses Tutorials sehen Sie eine voll funktionsf?hige Demo, die in Angular und Node.js geschrieben wurde. Traditionelle Authentifizierungssysteme Bevor wir zu tokenbasierten Authentifizierungssystemen übergehen, werfen wir einen Blick auf traditionelle Authentifizierungssysteme. Der Benutzer gibt seinen Benutzernamen und sein Passwort im Anmeldeformular ein und klickt auf ?Anmelden“. Nachdem Sie die Anfrage gestellt haben, authentifizieren Sie den Benutzer im Backend, indem Sie die Datenbank abfragen. Wenn die Anfrage gültig ist, wird eine Sitzung mit den aus der Datenbank erhaltenen Benutzerinformationen erstellt und die Sitzungsinformationen werden im Antwortheader zurückgegeben, sodass die Sitzungs-ID im Browser gespeichert wird. Bietet Zugriff auf Anwendungen, die unterliegen

Winkelkomponenten und ihre Anzeigeeigenschaften: Nicht-Block-Standardwerte verstehen Winkelkomponenten und ihre Anzeigeeigenschaften: Nicht-Block-Standardwerte verstehen Mar 15, 2024 pm 04:51 PM

Das Standardanzeigeverhalten für Komponenten im Angular-Framework gilt nicht für Elemente auf Blockebene. Diese Designwahl f?rdert die Kapselung von Komponentenstilen und ermutigt Entwickler, bewusst zu definieren, wie jede Komponente angezeigt wird. Durch explizites Festlegen der CSS-Eigenschaft display kann die Anzeige von Angular-Komponenten vollst?ndig gesteuert werden, um das gewünschte Layout und die gewünschte Reaktionsf?higkeit zu erreichen.

See all articles