SoFunction
Updated on 2025-04-04

Analyzing the source code example of Angular Component

Web Component

Before introducing Angular Component, let's take a brief look at itW3C Web Components

definition

W3C proposes Web Component standards as a unified component standard.

Each component contains its own HTML, CSS, and JS code.
The Web Component standard includes the following four important concepts:
Elements: You can create custom HTML tags and elements;
Templates (HTML template): Use the <template> tag to predefined some content, but it is not loaded to the page, but uses JS code to initialize it;
DOM (virtual DOM): It is possible to create DOM subtrees that are completely independent of other elements;
Imports: A method to introduce other HTML documents into HTML documents, <link rel="import" href="" rel="external nofollow" />.

In summary, it is possible to create custom tags to introduce components to the basis of front-end componentization. References to HTML files and HTML templates on the page are used to support writing component views and component resource management, while Shadow DOM isolates the conflicts and impacts of code between components.

Example

Definition hello-component

&lt;template &gt;
  &lt;style&gt;
    h1 {
      color: red;
    }
  &lt;/style&gt;
  &lt;h1&gt;Hello Web Component!&lt;/h1&gt;
&lt;/template&gt;

&lt;script&gt;

  // Point to the import document, that is, the  var indexDoc = document;

  // Point to the imported document, that is, the current document  var helloDoc = (indexDoc._currentScript || ).ownerDocument;

  // Get the template above  var tmpl = ('#hello-template');

  // Create a prototype of a new element, inherited from HTMLElement  var HelloProto = ();

  // Set Shadow DOM and clone the contents of the template in   = function() {
    var root = ();
    ((, true));
  };

  // Register new elements  var hello = ('hello-component', {
    prototype: HelloProto
  });
&lt;/script&gt;

Using hello-component

&lt;!DOCTYPE html&gt;
&lt;html lang="zh-cn"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta http-equiv="X-UA-COMPATIBLE" content="IE=edge"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
  &lt;meta name="author" content="Lai Xiangran, laixiangran@, "/&gt;
  &lt;title&gt;Web Component&lt;/title&gt;
  &lt;!--Import custom components--&gt;
  &lt;link rel="import" href="" rel="external nofollow" &gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;!--Custom Tags--&gt;
  &lt;hello-component&gt;&lt;/hello-component&gt;
&lt;/body&gt;
&lt;/html&gt;

From the above code, we can see that for a component defined by the standard (named hello-component), there is its own structure, style and logic in this component. Then, the component file is introduced in it, and it can be used like a normal label.

Angular Component

Angular Component is a type of directive, which can be understood as a directive with a template. The other two are attribute instructions and structure instructions.

Basic composition

@Component({
  selector: 'demo-component',
  template: 'Demo Component'
})
export class DemoComponent {}
  1. Component Decorator: Each component class must be decorated with @component to become an Angular component.
  2. Component metadata: Component metadata: selector, template, etc. The following will focus on explaining the meaning of each metadata.
  3. Component class: Components are actually also ordinary classes, and the logic of components is defined and implemented in component classes.
  4. Component template: Each component will be associated with a template, and this template will eventually be rendered on the page. The DOM element on the page is the host element of this component instance.

Component metadata

Its own metadata attributes

name type effect
animations AnimationEntryMetadata[] Set the component animation
changeDetection ChangeDetectionStrategy Setting up component change monitoring strategies
encapsulation ViewEncapsulation Set the view wrapper options for components
entryComponents any[] Set the list of components that will be dynamically inserted into the component view
interpolation [string, string] Interpolation marks for custom components, default to double braces
moduleId string Sets the module id of this component under the ES/CommonJS specification, which is used to parse the relative path of the template style
styleUrls string[] Set external style files referenced by components
styles string[] Set the inline style used by the component
template string Set up the component's inline template
templateUrl string Set the path where the component template is located
viewProviders Provider[] Set up the services available to the component and all its subcomponents (excluding ContentChildren)

Inherited from core/Directive

name type effect
exportAs string Sets the alias of component instances in the template so that they can be called in the template
host {[key: string]: string} Sets the events, actions, properties, etc. of the component
inputs string[] Set the input properties of the component
outputs string[] Set the output properties of the component
providers Provider[] Sets the available services (dependency injection) for the component and all its subcomponents (including ContentChildren)
queries {[key: string]: any} Set up queries that need to be injected into the component
selector string Set the css selector (component's custom tag) to identify the component in the template

Several metadata explanations

The following equivalent writing methods for metadata will be more concise and easy to understand than metadata settings, so the general recommendation is the equivalent writing method.

inputs

@Component({
  selector: 'demo-component',
  inputs: ['param']
})
export class DemoComponent {
  param: any;
}

Equivalent to:

@Component({
  selector: 'demo-component'
})
export class DemoComponent {
  @Input() param: any;
}

outputs

@Component({
  selector: 'demo-component',
  outputs: ['ready']
})
export class DemoComponent {
  ready = new eventEmitter<false>();
}

Equivalent to:

@Component({
  selector: 'demo-component'
})
export class DemoComponent {
  @Output() ready = new eventEmitter<false>();
}

host

@Component({
  selector: 'demo-component',
  host: {
    '(click)': 'onClick($)', // event    'role': 'nav', // Attributes    '[]': 'isPressed', // kind  }
})
export class DemoComponent {
  isPressed: boolean = true;

  onClick(elem: HTMLElement) {
    (elem);
  }
}

Equivalent to:

@Component({
  selector: 'demo-component'
})
export class DemoComponent {
  @HostBinding('') role = 'nav';
  @HostBinding('') isPressed: boolean = true;

 
  @HostListener('click', ['$'])
  onClick(elem: HTMLElement) {
    (elem);
  }
}

queries - View Query

@Component({
  selector: 'demo-component',
  template: `
    <input #theInput type='text' />
    <div>Demo Component</div>
  `,
  queries: {
    theInput: new ViewChild('theInput')
  }
})
export class DemoComponent {
  theInput: ElementRef;
}

Equivalent to:

@Component({
  selector: 'demo-component',
  template: `
    <input #theInput type='text' />
    <div>Demo Component</div>
  `
})
export class DemoComponent {
  @ViewChild('theInput') theInput: ElementRef;
}

queries - Content Query

<my-list>
  <li *ngFor="let item of items;">{{item}}</li>
</my-list>
@Directive({
  selector: 'li'
})
export class ListItem {}
@Component({
  selector: 'my-list',
  template: `
    <ul>
      <ng-content></ng-content>
    </ul>
  `,
  queries: {
    items: new ContentChild(ListItem)
  }
})
export class MyListComponent {
  items: QueryList<ListItem>;
}

Equivalent to:

@Component({
  selector: 'my-list',
  template: `
    <ul>
      <ng-content></ng-content>
    </ul>
  `
})
export class MyListComponent {
  @ContentChild(ListItem) items: QueryList<ListItem>;
}

styleUrls、styles

styleUrls and styles are allowed to be specified simultaneously.

Priority: Template inline styles > styleUrls > styles.

Recommendation: Use styleUrls to refer to external stylesheet files, so that the code structure is clearer and easier to manage than styles. Similarly, it is recommended to use templateUrl to reference template files.

changeDetection

: Each change monitoring of a component will check all data inside it (reference objects will also be traversed deeply) to obtain the previous and subsequent data changes.

: Component change monitoring only checks whether the value of the input attribute (i.e., the variable modified by @Input) has changed. When this value is a reference type (Object, Array, etc.), only the reference of the value is compared.

Obviously, the OnPush strategy reduces the complexity of change monitoring compared to Default, which greatly improves the performance of change monitoring. If the update of a component depends only on the value of the input attribute, then using the OnPush strategy on that component is a good choice.

encapsulation

: No Shadow DOM, and no style wrapping.

: No Shadow DOM, but the style wrapping mechanism provided by Angular simulates component independence, so that the style of component is not affected by external influences. This is the default setting of Angular.

: Use native Shadow DOM features.

life cycle

When Angular creates a new component using the constructor, these life cycle hook methods are called at a specific moment in the following order:

Life cycle hook Call time
ngOnChanges Called before ngOnInit, or when component input data (those variables explicitly specified via the @Input decorator) change.
ngOnInit Called after the first ngOnChanges. It is recommended to get the data at this time and do not get it in the constructor.
ngDoCheck Called every time the change monitoring occurs.
ngAfterContentInit use
ngAfterContentChecked ngAfterContentInit is called after, or is called every time the change monitoring occurs (components only).
ngAfterViewInit The view of the component and its subviews are called after creating (components only).
ngAfterViewChecked ngAfterViewInit, or is called every time the child component changes are monitored (components only).
ngOnDestroy Triggered before destroying the directive/component. At this time, resources that are not automatically recycled by the garbage collector (such as subscribed observer events, bound DOM events, timers set through setTimeout or setInterval, etc.) should be manually destroyed.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.