美文网首页
15Angular templateRef和NgTemplate

15Angular templateRef和NgTemplate

作者: learninginto | 来源:发表于2020-12-27 13:03 被阅读0次
    templateRef
    • ViewChild

    获取当前组件模板中的元素(组件、ng-template、dom)

    {static:true}默认为false,控制在变更检测之前拿取实例。通常将其置为true,要求它在变更检测之后拿取。

    有时在一个变更检测周期内,监听的数值会发生变化,可以将操作的内容转为异步执行

    setTimeout(()=>{
        this.firstContain.createEmbeddedView(this.firstTpl);
    },0)
    
    • createEmbeddedView()

    创建一个视图,并把它附着到父视图的容器中

      // 获取模板中的元素(组件、ng-template、dom)
      @ViewChild('box') readonly boxEl: ElementRef;
      
      //template元素
      @ViewChild('firstTpl', { read: TemplateRef }) readonly firstTpl: TemplateRef<any>;
      @ViewChild('secondTpl', { read: TemplateRef }) readonly secondTpl: TemplateRef<any>;
      @ViewChild('thirdTpl', { read: TemplateRef }) readonly thirdTpl: TemplateRef<any>;
      @ViewChild('fourthTpl', { read: TemplateRef }) readonly fourTpl: TemplateRef<any>;
      @ViewChild('freeTpl', { read: TemplateRef }) readonly freeTpl: TemplateRef<any>;
      
      @ViewChild('firstContainer', { read: ViewContainerRef, static: true }) readonly firstContain: ViewContainerRef;
      @ViewChild('secondContainer', { read: ViewContainerRef, static: true }) readonly secondContain: ViewContainerRef;
      private freeViewRef: EmbeddedViewRef<any>;
    
    firstTpl:TemplateRef<any>;
    
    //DOM元素
    @ViewChild('box')readonly boxEl:ElementRef;
    
    //container
    @ViewChild('firstContainer',{read:ViewContianerRef}) readonly firstContain : ViewContainerRef
    
    ngAfterViewInit():void{
        console.log('ngAfterViewInit')
        console.log(this.firstTpl);
        //viewref.rootNodes下是当前dom节点里的元素
        this.boxEl.nativeElement.appendChild(viewref.rootNodes[0])
        
        //将firstTpl创建出来,插入到firstContainer中
        this.firstContain.createEmbeddedView(this.firstTpl)
    }
    
      insert(tpl: TemplateRef<any>) {
        this.firstContain.insert(tpl.createEmbeddedView(null));
      }
    
      insertAll() {
        [this.secondTpl, this.thirdTpl, this.fourTpl].forEach(tpl => {
          this.firstContain.insert(tpl.createEmbeddedView(null));
        });
      }
    
      getOne() {
        console.log(this.firstContain.get(2));
        console.log(this.firstContain.indexOf(this.freeViewRef));
      }
    
      insertFree() {
        this.firstContain.insert(this.freeViewRef, 1);
      }
    
      move() {
        // 不需要事先插入也可以移动(定好位置再插入)
        this.firstContain.move(this.freeViewRef, 2);
      }
    
      move2To4() {
        const view = this.firstContain.detach(1);
        this.firstContain.insert(view, 3);
      }
    
      move2ToOther() {
        const view = this.firstContain.detach(1);
        this.secondContain.insert(view);
      }
    
    
    • html
    <div class="box" #box>
      <button class="btn btn-primary mr-1" (click)="insert(secondTpl)">insert second</button>
      <button class="btn btn-primary mr-1" (click)="insert(thirdTpl)">insert third</button>
      <button class="btn btn-primary mr-1" (click)="insert(fourthTpl)">insert fourth</button>
      <button class="btn btn-primary mr-1" (click)="insertAll()">insert all</button>
      <button class="btn btn-secondary mr-1" (click)="insertFree()">insert free</button>
      <button class="btn btn-info mr-1" (click)="getOne()">get one</button>
      <button class="btn btn-success mr-1" (click)="move()">move free</button>
      <button class="btn btn-success mr-1" (click)="move2To4()">把第二个移动到第四个位置上</button>
      <button class="btn btn-success" (click)="move2ToOther()">把第二个移动到其他容器中</button>
      <p>长度:{{ firstContain?.length }}</p>
    </div>
    <ng-template #firstTpl>
      <p>first tpl content</p>
    </ng-template>
    
    
    <ng-template #secondTpl>
      <p>第二段template</p>
    </ng-template>
    
    <ng-template #thirdTpl>
      <p>第三段template</p>
    </ng-template>
    
    <ng-template #fourthTpl>
      <p>第四段template</p>
    </ng-template>
    
    <ng-template #freeTpl let-fr="free" let-def>
      <p>自由的template -- fr: {{ fr }} def: {{ def }}</p>
    </ng-template>
    
    <p>
      first container:
      <ng-container #firstContainer></ng-container>
    </p>
    
    <hr>
    
    <p>
      second container:
      <ng-container #secondContainer></ng-container>
    </p>
    
    NgTemplateOutlet

    根据一个提前备好的 TemplateRef 插入一个内嵌视图。

    import { Component, Input, TemplateRef } from '@angular/core';
    @Component({
      selector: 'app-tpl-outlet',
      template: `<div>
                   <ng-container *ngTemplateOutlet="render || defaultTpl; context: myContext"></ng-container>
                   <!--      <ng-container [ngTemplateOutlet]="render || defaultTpl" [ngTemplateOutletContext]="myContext"></ng-container>-->
                   
                   <!--   用在ng-template上也可以   -->
                   <!--      <ng-template *ngTemplateOutlet="render || defaultTpl; context: myContext"></ng-template>-->
                   <!--      <ng-template [ngTemplateOutlet]="render || defaultTpl" [ngTemplateOutletContext]="myContext"></ng-template>-->
                 </div>
                <ng-template #customTpl let-def let-val="value">
                  <b>customTpl rendered! def: {{ def }}; value: {{ val }}</b>
                </ng-template>`
    })
    export class TplOutletComponent  {
      @Input () render: TemplateRef<any>;
      myContext = {$implicit: 'World', value: 'Svet'};
    }
    
    • 调用TplOutletComponent传入自定义的dom
    import { Component, Input } from '@angular/core';
    @Component({
      selector: 'app-root',
      template: `<app-tpl-outlet [render]="render"></app-tpl-outlet>
                 <ng-template #render let-value="value">
                   <p><b>自定义的dom -- {{ value }}</b></p>
                 </ng-template>
              `
    })
    export class ItemDetailComponent  {
    
    }
    

    相关文章

      网友评论

          本文标题:15Angular templateRef和NgTemplate

          本文链接:https://www.haomeiwen.com/subject/ogdonktx.html