zoukankan      html  css  js  c++  java
  • angular--ng-template&ngTemplateOutlet的用法

     1.ng-template指令介绍--<ng-template></ng-template>

     ng-template表示一个模板,标签内是模板的内容,模板的内容可以与其它模板一起组成组件模板。

    在Angular中,我们用过的许多结构指令都使用了ng-template,如ngIf、ngFor和ngSwitch。

    ngTemplate中的内容可以自定义,并且一开始不会被渲染,除非满足一定的条件。我们必须使用结构指令去渲染它。

    <ng-template>
        <button class="tab-button" (click)="login()">{{loginText}}</button>
        <button class="tab-button" (click)="signUp()">{{signUpText}}</button>
    </ng-template>

    上面代码在页面中并没有被渲染。

    2.ng-template使用

    2.1ng-template与ngIf

    我们见的最多的可能是与ngIf一块使用,当if条件不成立时,将显示else中的内容。下面代码中else语句被指向了一个名为loading的模板,通过模板引用#loading的方式。

    1 <div class="lessons-list" *ngIf="lessons else loading">
    2   ... 
    3 </div>
    4 
    5 <ng-template #loading>
    6     <div>Loading...</div>
    7 </ng-template>

    其实,ngIf指令也是ng-template的包装。

    1 <ng-template [ngIf]="lessons" [ngIfElse]="loading">
    2    <div class="lessons-list">
    3      ... 
    4    </div>
    5 </ng-template>
    6 
    7 <ng-template #loading>
    8     <div>Loading...</div>
    9 </ng-template>

    [ngIf]和[ngIfElse]为模板输入变量。

    2.2同一元素使用多个结构指令

    1 <div class="lesson" *ngIf="lessons" 
    2        *ngFor="let lesson of lessons">
    3     <div class="lesson-detail">
    4         {{lesson | json}}
    5     </div>
    6 </div>  

    这样会报错:

    Uncaught Error: Template parse errors:
    Can't have multiple template bindings on one element. Use only one attribute 
    named 'template' or prefixed with *

    这意味着不能在同一个元素使用两个或多个结构指令。

    1 <div *ngIf="lessons">
    2     <div class="lesson" *ngFor="let lesson of lessons">
    3         <div class="lesson-detail">
    4             {{lesson | json}}
    5         </div>
    6     </div>
    7 </div>

    可以在ngFor指令的外面包一层ngIf指令,这样就解决了上面的问题;但这样会额外创一个一个元素。因此,我们可以使用ng-container指令。

    1 <ng-container *ngIf="lessons">
    2     <div class="lesson" *ngFor="let lesson of lessons">
    3         <div class="lesson-detail">
    4             {{lesson | json}}
    5         </div>
    6     </div>
    7 </ng-container>

    ng-container的一种用途是,给我们提供一个附加指令的元素而不会创建一个额外的元素。另一种用途是,配合ngTemplateOutlet使用。

    3.ngTemplateOutlet使用介绍

    ngTemplateOutlet也是一个指令,它使用模板引用和上下文对象作为参数动态实例化模板。作为一个结构指令,我们可以使用它在DOM的各个部分插入模板(由ng-template创建)。

     1 <ng-container *ngTemplateOutlet="loading">This text is not displayed</ng-container> 

    ngTemplateOutlet包含的任何内部内容都不会被渲染;我们可以根据需要向页面添加任意数量的ngTemplateOutlet标签,并实例化许多不同的模板。

     1 <div *ngTemplateOutlet="loading"></div>  

    上面代码中的div并不会被渲染,因为angular将上述内容替换成ng-template语法,

     1 <ng-template [ngTemplateOutlet]="template1"><div></div></ng-template> 

    3.1传递数据给ngTemplateOutlet

    我们可以通过ngTemplateOutletContext属性传递数据

    1 <ng-template let-value="value" #messageTemplate>  
    2     <p>Value Received from the Parent is  {{value}}</p>
    3 </ng-template>
    1 <ng-container [ngTemplateOutlet]="messageTemplate" 
    2        [ngTemplateOutletContext] ="{value:'1000'}">
    3 </ng-container> 

    当然,也可以使用简写属性--context:

     1 <ng-container *ngTemplateOutlet="messageTemplate; context:{value:100}"></ng-container>  传递多个数据:

    1 <ng-template let-name="nameVar" let-message="messageVar" #template>  
    2   <p>Dear {{name}} , {{message}} </p>
    3 </ng-template>
    4  
    5  
    6 <ng-container [ngTemplateOutlet]="template" 
    7           [ngTemplateOutletContext] ="{nameVar:'Guest',messageVar:'Welcome to our site'}">
    8 </ng-container> 

    传递对象:

    1  
    2 <ng-template let-person="person"  #template>  
    3   <p>Dear {{person.name}} , {{person.message}} </p>
    4 </ng-template>
    5  
    6  
    7 <ng-container [ngTemplateOutlet]="template" 
    8            [ngTemplateOutletContext] ="{ person:{name:'Guest',message:'Welcome to our site'} }">
    9 </ng-container> 

    使用$implicit:

    可以在上下文对象中使用$implicit将其值设置为所有局部变量的默认值。

    1 <ng-template let-name let-message="message" #template3>  
    2   <p>Dear {{name}} , {{message}} </p>
    3 </ng-template>
    4  
    5 <ng-container [ngTemplateOutlet]="templates" 
    6               [ngTemplateOutletContext] ="{$implicit:'Guest',message:'Welcome to our site'}">
    7 </ng-container> 

    上面代码中,我们没有给 let-name 赋值,因此它从$implicit中获取值。

    3.2模板上下文

    每个模板可以定义自己的输入变量;实际上,每个模板都关联了一个上下文对象,其中包含所有特定于模板的输入变量。

     1 @Component({
     2   selector: 'app-root',
     3   template: `      
     4 <ng-template #estimateTemplate let-lessonsCounter="estimate">
     5     <div> Approximately {{lessonsCounter}} lessons ...</div>
     6 </ng-template>
     7 <ng-container 
     8    *ngTemplateOutlet="estimateTemplate;context:ctx">
     9 </ng-container>
    10 `})
    11 export class AppComponent {
    12 
    13     totalEstimate = 10;
    14     ctx = {estimate: this.totalEstimate};
    15   
    16 }

    说明:lessonsCounter为输入变量,通过ng-template属性使用前缀 let- 定义的

    lessonsCounter对ng-template模板里面的内容是可见的,对模板外是不可见的。

    lessonsCounter的值是由 estimate 决定的,故context 对象必须有一个estimate 的属性。

    3.3 模板引用

    我们可以使用ViewChild装饰器将模板直接注入到组件中:

     1 @Component({
     2   selector: 'app-root',
     3   template: `      
     4       <ng-template #defaultTabButtons>
     5           <button class="tab-button" (click)="login()">
     6             {{loginText}}
     7           </button>
     8           <button class="tab-button" (click)="signUp()">
     9             {{signUpText}}
    10           </button>
    11       </ng-template>
    12 `})
    13 export class AppComponent implements OnInit {
    14 
    15     @ViewChild('defaultTabButtons')
    16     private defaultTabButtonsTpl: TemplateRef<any>;
    17 
    18     ngOnInit() {
    19         console.log(this.defaultTabButtonsTpl); //undefined; ngAfterViewInit()才会打印
    20     }
    21 
    22 }

    模板可以被注入,就像DOM元素和组件一样,通过将模板引用传给ViewChild装饰器。

    我们还可以将模板作为一个输入变量:

     1 @Component({
     2   selector: 'app-root',
     3   template: `      
     4 <ng-template #customTabButtons>
     5     <div class="custom-class">
     6         <button class="tab-button" (click)="login()">
     7           {{loginText}}
     8         </button>
     9         <button class="tab-button" (click)="signUp()">
    10           {{signUpText}}
    11         </button>
    12     </div>
    13 </ng-template>
    14 <tab-container [headerTemplate]="customTabButtons"></tab-container>      
    15 `})
    16 export class AppComponent implements OnInit {
    17 
    18 }
     1 @Component({
     2     selector: 'tab-container',
     3     template: `
     4     
     5 <ng-template #defaultTabButtons>
     6     
     7     <div class="default-tab-buttons">
     8         ...
     9     </div>
    10     
    11 </ng-template>
    12 <ng-container 
    13   *ngTemplateOutlet="headerTemplate ? headerTemplate: defaultTabButtons">
    14     
    15 </ng-container>
    16 ... rest of tab container component ...
    17 `})
    18 export class TabContainerComponent {
    19     @Input()
    20     headerTemplate: TemplateRef<any>;
    21 }

    当我们传入自定义模板时(#customTabButtons),就显示这个自定义模板;否则,显示默认的模板。

    3.4 ngTemplateOutlet、ng-template 与内容投影

    父组件使用内容投影传递一个模板给子组件:

     1 import { Component, TemplateRef, Input, OnInit, ViewChild, AfterViewInit } from '@angular/core';
     2  
     3 @Component({
     4   selector: 'parent1',
     5   template: `
     6   
     7   <h1>Parent Component </h1>
     8  
     9   <child1> 
    10     <p>This Template is Projected to the Child</p>
    11   </child1>
    12   `
    13 })
    14 export class Parent1Component {
    15 }

    子组件:

     1 import { Component, TemplateRef, Input, OnInit, ViewChild, AfterViewInit } from '@angular/core';
     2  
     3 @Component({
     4   selector: 'child1',
     5   template: `
     6  
     7   <h1>Child Component </h1>
     8  
     9   <ng-template #parentTemplate>
    10     <ng-content></ng-content>
    11   </ng-template>
    12  
    13   <ng-template [ngTemplateOutlet]="parentTemplate"></ng-template>
    14  
    15   `
    16 })
    17 export class Child1Component {
    18 }
    19  

    4.总结

    ng-template、ng-container和ngTemplateOutlet指令结合使用,可以创建高度动态和可定制的组件。

     
  • 相关阅读:
    【WebTerminal】gotty工具
    【Java】15分钟快速体验阿里Java诊断工具Arthas
    【K8S】helm chart多环境部署最佳实践-示例
    mysql-linux定时备份mysql数据库
    Mockito-简单使用使用
    EasyMock 简单使用
    SpringDataJpa学习
    js-重写jquery的ajax中的内容
    shiro-过滤器
    hadoop ha 读取 activce状态的活动节点
  • 原文地址:https://www.cnblogs.com/sparkler/p/15490689.html
Copyright © 2011-2022 走看看