template报错_ng-template、ng-container、ngTemplateOutlet 三兄弟

53df3da0a2da67765e6bc92c0a1d7a2e.png

今天,我们将研究Angular的ng-template、ng-templateOutlet及ng-container指令。在此之前,相信你们已经遇到过Angular中的一些指令,比如用过的ngIf跟ngSwitch指令。

Angular中的ng-template指令和与之相关的ngTemplateOutlet指令,如果使用得到,将会事半功倍。下面我们通过对这三个指令提供相应常见的 来学习及了解他们的使用。

  • ng-template指令

见名知意,ng-template指令是一个包容性指令,类比学习你可以将它与vue中的slot比较,但是区别是有的,这里不详细展开。在Angular框架本身的组件或指令中,也经常会看到ng-template影子,比如ngIf、ngFor及ngSwitch。下面我们来看一个例子:

@Component({
  selector: 'app-root',
  template: `      
      <ng-template>
          <button class="tab-button" 
                  (click)="login()">{{loginText}}</button>
          <button class="tab-button" 
                  (click)="signUp()">{{signUpText}}</button>
      </ng-template>
  `})
export class AppComponent {
    loginText = 'Login';
    signUpText = 'Sign Up'; 
    lessons = ['Lesson 1', 'Lessons 2'];

    login() {
        console.log('Login');
    }

    signUp() {
        console.log('Sign Up');
    }
}

当你运行上面的组件时,其实组件什么也没有渲染,这是为什么呢?这是因为ng-template只是声明了一个组件模板,而我们还没有用它。你可能会见过这样的模板写法:

<div class="lessons-list" *ngIf="lessons else loading">
  ... 
</div>

<ng-template #loading>
    <div>Loading...</div>
</ng-template>

这是一个很常见的写法,当我们在ajax请求数据的时候,可能需要一些loading效果。所以在这里是相当于在请求完成之前,声明使用由ng-template声明的模板。当然,这种写法也可以:

<div class="lessons-list" [ngIf]="lessons" [ngIfElse]="loading">
  ... 
</div>

<ng-template #loading>
    <div>Loading...</div>
</ng-template>
  • 多重指令

当我们同时使用ngIf与ngFor指令的时候,猜猜会怎样呢?

<div class="lesson" *ngIf="lessons" 
       *ngFor="let lesson of lessons">
    <div class="lesson-detail">
        {{lesson | json}}
    </div>
</div>

试试运行下,你会发现控制台会报错:

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

简单理解下就是不能同时在同一个dom元素上的。开发vue组件时,如果没有用一个root容器包裹就会报错。显然,这些会增加多余的dom元素。那么在Angular中,使用ng-container就不会存在这个问题,如下:

<ng-container *ngIf="lessons">
    <div class="lesson" *ngFor="let lesson of lessons">
        <div class="lesson-detail">
            {{lesson | json}}
        </div>
    </div>
</ng-container>
  • 动态插槽ngTemplteOutlet

熟悉vue开发的同学知道,vue中有一个插槽的概念,这里是做类别学习,借用这个概念会增加你对ngTemplateOutlet的理解。使用ng-container跟ngTemplateOutlet,可以在组件的任何地方动态插入你想要的模板:

<ng-container *ngTemplateOutlet="loading"></ng-container>

这里同时要说的是ngTemplateOutlet跟声明它的组件享有同一个作用域。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对不起,我理解错了您的要求。要使用ng-template来调用方法,您可以按照以下步骤操作: 1. 在组件中声明一个TemplateRef变量,并将其注入到构造函数中。例如: ```typescript constructor(private templateRef: TemplateRef<any>) { } ``` 2. 在模板中使用ng-template,并将其绑定到一个变量上。例如: ```html <ng-template #myTemplate> <button (click)="myMethod()">调用方法</button> </ng-template> ``` 3. 在组件中定义一个方法,该方法将使用ViewContainerRef来创建一个嵌入视图,并将ng-template作为参数传递给createEmbeddedView方法。例如: ```typescript import { ViewContainerRef } from '@angular/core'; myMethod() { this.viewContainerRef.clear(); this.viewContainerRef.createEmbeddedView(this.templateRef); } ``` 请注意,我还添加了`ViewContainerRef`作为依赖注入,并在`myMethod`方法中使用了`clear`方法来清除视图容器中的任何现有内容。 4. 在组件的模板中,使用`ng-container`来放置嵌入视图。例如: ```html <ng-container #container></ng-container> ``` 5. 在组件的类中,使用ViewChild装饰器来获`ViewContainerRef`的引用。例如: ```typescript @ViewChild('container', { read: ViewContainerRef }) viewContainerRef: ViewContainerRef; ``` 这样,当调用`myMethod()`方法时,将会创建一个嵌入视图,并将ng-template的内容插入到`ng-container`中。 希望这样能满足您的要求!如果您还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值