What is the difference between createEmbeddedView and createComponent?

后端 未结 1 399
日久生厌
日久生厌 2020-12-13 20:43

I am confused between use cases of createEmbeddedView and createComponent, i.e when to use which one.

Please come up with some cases that c

相关标签:
1条回答
  • 2020-12-13 21:28

    See this workshop on DOM manipulation or read Working with DOM in Angular: unexpected consequences and optimization techniques where I explain the difference with examples.

    These both methods are used to dynamically add content to the component view (DOM). This content can be either a template or a component based. In Angular we usually manipulate the DOM using ViewContainerRef. And both these methods are available on it:

    class ViewContainerRef {
        ...
        createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C>
        createComponent<C>(componentFactory: ComponentFactory<C>, index?: number, injector?: Injector, projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>
    }
    

    To learn more about manipulating the DOM read Exploring Angular DOM manipulation techniques using ViewContainerRef.

    createEmbeddedView

    It's used to create a view using TemplateRef. TemplateRef is created by Angular compiler when it encounters ng-template tag in your component html. The view created using this method is called an embedded view.

    import { VERSION, Component, ViewChild, TemplateRef, ViewContainerRef } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template: `
          <ng-container #vc></ng-container>
          <ng-template #tpl>
              <h1>Hello, {{name}}</h1>
          </ng-template>
      `,
      styles: ['']
    })
    export class AppComponent {
      name = `Angular! v${VERSION.full}`;
    
      @ViewChild('tpl', {read: TemplateRef}) tpl: TemplateRef<any>;
      @ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;
    
      ngOnInit() {
        this.vc.createEmbeddedView(this.tpl);
      }
    }
    

    Stackblitz demo

    This approach is used by all structural directives like *ngIf and *ngFor because they are all wrap a ng-template. For example, for *ngIf the code:

    <div *ngIf="data">{{name}}</div>
    

    is transformed into

    <ng-template ngIf="data">
       <div>{{name}}</div>
    

    And the ngIf directive uses createEmbeddedView internally:

    @Directive({selector: '[ngIf]'})
    export class NgIf {
        private _updateView() {
           ...
           if (this._thenTemplateRef) {
               this._thenViewRef =
                   this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context);
    

    createComponent

    It's used to create a view using ComponentFactory. It's created by Angular compiler when you specify a component in the bootstrap property of the module and so the compiler generates a factory for it. The view created using this method is called a hostview.

    import { Component, ViewContainerRef, ComponentFactoryResolver, NgZone, VERSION, ViewChild } from '@angular/core';
    
    @Component({
      selector: 'hello',
      template: `<h1>Hello Component!</h1>`,
      styles: [``]
    })
    export class HelloComponent  {}
    
    @Component({
      selector: 'my-app',
      template: `
          <ng-container #vc></ng-container>
      `,
      styles: ['']
    })
    export class AppComponent {
    
      @ViewChild('vc', {read:ViewContainerRef}) vc: ViewContainerRef;
    
      constructor(private resolver: ComponentFactoryResolver) {}
    
      ngOnInit() {
        const factory = this.resolver.resolveComponentFactory(HelloComponent);
        this.vc.createComponent(factory);
      }
    }
    

    Stackblitz demo.

    To learn more about the difference between a host view and an embedded view read What is the difference between a view, a host view and an embedded view

    0 讨论(0)
提交回复
热议问题