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

Table of Contents
Decorators and metadata
Decorators and metadata in Angular
總結(jié)
Home Web Front-end JS Tutorial Let's talk about metadata and decorators in Angular

Let's talk about metadata and decorators in Angular

Feb 28, 2022 am 11:10 AM
angular

This article continues the learning of Angular, takes you to understand the metadata and decorators in Angular, and briefly understands their usage. I hope it will be helpful to everyone!

Let's talk about metadata and decorators in Angular

As a front-end framework designed “for large-scale front-end projects”, Angular actually has many designs worthy of reference and learning. This series is mainly used to study these designs and functions. Realization principle. This article mainly introduces metadata that can be found everywhere in Angular. [Related tutorial recommendations: "angular tutorial"]

Decorators are the core concept when developing using Angular. In Angular, decorators are used to attach metadata to classes or properties to let you know what those classes or properties mean and how to deal with them.

Decorators and metadata

Neither decorators nor metadata are concepts proposed by Angular. So let’s take a quick look at it first.

Metadata

In a general concept, metadata is data that describes user data. It summarizes basic information about the data and can make it easier to find and use specific data instances. For example, author, creation date, modification date, and file size are examples of very basic document metadata.

In the scenario used for classes, metadata is used to decorate the class to describe the definition and behavior of the class so that the expected behavior of the class can be configured.

Decorator

Decorator is a language feature of JavaScript, which is located in stage 2. Test characteristics.

Decorators are functions called on a class, class element, or other JavaScript syntax form during definition.

Decorators have three main functions:

  • You can replace the value being decorated with a matching value with the same semantics. (For example, a decorator can replace a method with another method, one field with another field, one class with another class, and so on).

  • Metadata can be associated with the value being decorated; this metadata can be read externally and used for metaprogramming and self-inspection.

  • Access to the value being modified can be provided through metadata. For public values, they do so via the value name; for private values, they receive accessor functions, which can then optionally be shared.

Essentially, decorators can be used to metaprogram a value and add functionality to it without fundamentally changing its external behavior.

For more information, please refer to tc39/proposal-decorators proposal.

Decorators and metadata in Angular

When we develop Angular applications, whether they are components, instructions, services, modules, etc., they all need to be defined and developed through decorators. Decorators appear immediately before a class definition and are used to declare that the class has a specified type and provide metadata suitable for that type.

For example, we can use the following decorators to declare Angular classes: @Component(), @Directive(), @Pipe(), @Injectable(), @NgModule().

Use decorators and metadata to change the behavior of a class

Take @Component() as an example, the The functions of the decorator include:

  • Mark the class as an Angular component.

  • Provides configurable metadata that determines how the component should be processed, instantiated, and used at runtime.

For how to use @Component(), you can refer to , I won’t introduce it here. Let’s take a look at the definition of this decorator:

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

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

The above is the definition of component decoration and component metadata. Let’s take a look at the creation process of the decorator.

The creation process of the decorator

We can find it from the source code. The decorators of components and instructions will pass makeDecorator() To generate:

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 很重要,因?yàn)樗鼤?huì)創(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;
  });
}

In the above example, we use makeDecorator() to generate a Component decorator factory for defining components. When you create a component using @Component(), Angular compiles the component based on the metadata.

Compile the component based on the decorator metadata

Angular will compile the Angular component based on the decorator metadata, and then convert the generated component Definition (?cmp) is patched onto the component type:

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);
  // 這里使用的功能與指令相同,因?yàn)檫@只是創(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,
        };
        // 編譯過程需要計(jì)算深度,以便確認(rèn)編譯是否最終完成
        compilationDepth++;
        try {
          if (meta.usesInheritance) {
            addDirectiveDefToUndecoratedParents(type);
          }
          // 根據(jù)模板、環(huán)境和組件需要的元數(shù)據(jù),來編譯組件
          ngComponentDef = compiler.compileComponent(angularCoreEnv, templateUrl, meta);
        } finally {
          // 即使編譯失敗,也請(qǐng)確保減少編譯深度
          compilationDepth--;
        }
        if (compilationDepth === 0) {
          // 當(dāng)執(zhí)行 NgModule 裝飾器時(shí),我們將模塊定義加入隊(duì)列,以便僅在所有聲明都已解析的情況下才將隊(duì)列出隊(duì),并將其自身作為模塊作用域添加到其所有聲明中
          // 此調(diào)用運(yùn)行檢查以查看隊(duì)列中的任何模塊是否可以出隊(duì),并將范圍添加到它們的聲明中
          flushModuleScopingQueueAsMuchAsPossible();
        }
        // 如果組件編譯是異步的,則聲明該組件的 @NgModule 批注可以執(zhí)行并在組件類型上設(shè)置 ngSelectorScope 屬性
        // 這允許組件在完成編譯后,使用模塊中的 directiveDefs 對(duì)其自身進(jìn)行修補(bǔ)
        if (hasSelectorScope(type)) {
          const scopes = transitiveScopesFor(type.ngSelectorScope);
          patchComponentDefWithScope(ngComponentDef, scopes);
        }
      }
      return ngComponentDef;
    },
    ...
  });
}

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

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

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

在 Angular 中,編譯過程產(chǎn)生的元數(shù)據(jù),會(huì)使用CompileMetadataResolver來進(jìn)行管理和維護(hù),這里我們主要看指令(組件)相關(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) {}
  // 清除特定某個(gè)指令的元數(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);
      }
      // 存儲(chǔ)完整的元數(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ù)進(jìn)行存儲(chǔ)
      return SyncAsync.then(templateMeta, createDirectiveMetadata);
    } else {
      // 指令,直接存儲(chǔ)元數(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來存儲(chǔ)。

總結(jié)

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

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

更多編程相關(guān)知識(shí),請(qǐng)?jiān)L問:編程教學(xué)!!

The above is the detailed content of Let's talk about metadata and decorators in Angular. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Metadata scraping using the New York Times API Metadata scraping using the New York Times API Sep 02, 2023 pm 10:13 PM

Introduction Last week, I wrote an introduction about scraping web pages to collect metadata, and mentioned that it was impossible to scrape the New York Times website. The New York Times paywall blocks your attempts to collect basic metadata. But there is a way to solve this problem using New York Times API. Recently I started building a community website on the Yii platform, which I will publish in a future tutorial. I want to be able to easily add links that are relevant to the content on my site. While people can easily paste URLs into forms, providing title and source information is time-consuming. So in today's tutorial I'm going to extend the scraping code I recently wrote to leverage the New York Times API to collect headlines when adding a New York Times link. Remember, I'm involved

How to install Angular on Ubuntu 24.04 How to install Angular on Ubuntu 24.04 Mar 23, 2024 pm 12:20 PM

Angular.js is a freely accessible JavaScript platform for creating dynamic applications. It allows you to express various aspects of your application quickly and clearly by extending the syntax of HTML as a template language. Angular.js provides a range of tools to help you write, update and test your code. Additionally, it provides many features such as routing and form management. This guide will discuss how to install Angular on Ubuntu24. First, you need to install Node.js. Node.js is a JavaScript running environment based on the ChromeV8 engine that allows you to run JavaScript code on the server side. To be in Ub

A brief analysis of how to use monaco-editor in angular A brief analysis of how to use monaco-editor in angular Oct 17, 2022 pm 08:04 PM

How to use monaco-editor in angular? The following article records the use of monaco-editor in angular that was used in a recent business. I hope it will be helpful to everyone!

How to use PHP and Angular for front-end development How to use PHP and Angular for front-end development May 11, 2023 pm 04:04 PM

With the rapid development of the Internet, front-end development technology is also constantly improving and iterating. PHP and Angular are two technologies widely used in front-end development. PHP is a server-side scripting language that can handle tasks such as processing forms, generating dynamic pages, and managing access permissions. Angular is a JavaScript framework that can be used to develop single-page applications and build componentized web applications. This article will introduce how to use PHP and Angular for front-end development, and how to combine them

Detailed explanation of angular learning state manager NgRx Detailed explanation of angular learning state manager NgRx May 25, 2022 am 11:01 AM

This article will give you an in-depth understanding of Angular's state manager NgRx and introduce how to use NgRx. I hope it will be helpful to you!

An article exploring server-side rendering (SSR) in Angular An article exploring server-side rendering (SSR) in Angular Dec 27, 2022 pm 07:24 PM

Do you know Angular Universal? It can help the website provide better SEO support!

Access metadata of various audio and video files using Python Access metadata of various audio and video files using Python Sep 05, 2023 am 11:41 AM

We can access the metadata of audio files using Mutagen and the eyeD3 module in Python. For video metadata we can use movies and the OpenCV library in Python. Metadata is data that provides information about other data, such as audio and video data. Metadata for audio and video files includes file format, file resolution, file size, duration, bitrate, etc. By accessing this metadata, we can manage media more efficiently and analyze the metadata to obtain some useful information. In this article, we will take a look at some of the libraries or modules provided by Python for accessing metadata of audio and video files. Access audio metadata Some libraries for accessing audio file metadata are - using mutagenesis

Token-based authentication with Angular and Node Token-based authentication with Angular and Node Sep 01, 2023 pm 02:01 PM

Authentication is one of the most important parts of any web application. This tutorial discusses token-based authentication systems and how they differ from traditional login systems. By the end of this tutorial, you will see a fully working demo written in Angular and Node.js. Traditional Authentication Systems Before moving on to token-based authentication systems, let’s take a look at traditional authentication systems. The user provides their username and password in the login form and clicks Login. After making the request, authenticate the user on the backend by querying the database. If the request is valid, a session is created using the user information obtained from the database, and the session information is returned in the response header so that the session ID is stored in the browser. Provides access to applications subject to

See all articles