网站首页 » 前端开发 » Angular 2+ » Angular 2+ 结构型指令
上一篇:
下一篇:

Angular 2+ 结构型指令

前言

结构型指令跟属性型指令很相似,但它们的实现原理有很大的不同,属性型指令一般都是为了更改元素的外观或行为比如:内置的NgStyle指令,而结构型指令更多的则是更改了 HTML 结构。

结构指令之旅

什么是结构型指令

结构型指令主要的作用是 HTML 布局,即增删元素。这个增删元素是彻底的,它不像样式中的 display:none 那样只是让你看不过,而是直接从 HTML 中移除了。这样可以使得 HTML 更精简。

在 Angular 2+ 中有几个比较常用的内置结构型指令: NgIf、NgFor和NgSwitch。对于刚学习 Angular 2+ 的人来说知道这三个就已经可以实现基本的项目需求了。至于他们的用法,你只需要看一眼就大概知道了:

简单得不像样
<div *ngIf="person">{{person.age}}</div>

<ul>
  <li *ngFor="let person of persons">{{person.name}}今年 {{person.age}} 岁</li>
</ul>

<div [ngSwitch]="person?.age">
  <div *ngSwitchCase="'12'">内容一</div>
  <div *ngSwitchCase="'13'">内容二</div>
  <div *ngSwitchCase="'14'">内容三</div>
  <div *ngSwitchDefault>内容四</div>
</div>

* ng-if 接收一个布尔值(true|false),ngSwitch 接收一个值作为条件。

Angular 2+ 把 *ngIf、ngFor 和 ngSwitch 属性翻译成一个<ng-template> 元素,并用它来包裹宿主元素及其子元素。上面的代码运行后查看浏览器渲染出来的 HTML 如下:

Angular 2+ 结构型指令

可以看到 <ng-template> 是一个Angular 元素,用来渲染HTML。但它并没有跟着 HTML 元素一起出现在页面中,而是以一个注释的形式存在。因为在渲染视图之前,Angular 2+会把<ng-template>及其内容替换为一个注释,所以你可以放心使用。

<ng-template> 要配合结构型指令一起使用才会有效果,否则 <ng-template>  正常工作,放在 <ng-template>  中的元素内容是不会显示到页面中。

在这里我们不妨把官方的一段代码拷贝过来:

<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
  ({{i}}) {{hero.name}}
</div>

<ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
  <div [class.odd]="odd">({{i}}) {{hero.name}}</div>
</ng-template>

这一段代码把 *ngFor 的运行结果展示得清清楚楚,*ngFor 运行后会先转换成下面带有 <ng-template> 代码,然后再进行后继工作。

每个宿主元素上只能有一个结构型指令,这个是什么意思呢?请看下面这一段代码:

<ul>
  <li *ngFor="let person of persons" *ngIf="true">{{person.name}} 今年 {{person.age}} 岁</li>
</ul>

li 元素中同时使用了 *ngFor 和 *ngIf。这时你就会看到浏览器中会给你送上了一个报错信息:

报错

Uncaught Error: Template parse errors:

Can’t have multiple template bindings on one element. Use only one attribute named ‘template’ or prefixed with * (“

大概意思就是说一个元素上不能绑定多个模板。如果要想实现我们想要的效果的话,我们可以像下面这样对代码进行改进:

<ul>
  <li *ngFor="let person of persons;let even = even">
    <ng-container *ngIf="even">{{person.name}} 今年 {{person.age}} 岁</ng-container>
  </li>
</ul>

ng-template 和 ng-container 的区别

上面我们借用了<ng-container> 来实现我们想要的效果,这个也是一个 Angular 2+ 元素,与 <ng-template>  非常地像。但是在这里不能直接用<ng-template>。为什么?当你把 <ng-container> 替换成 <ng-template> 后,虽然没有报错,但是 < ng-template> 中的内容却不显示在页面中了。在这里我们需要注意一点,< ng-template> 和 < ng-container> 的用法有些许不同,但这一点很重要。在 < ng-template> 中使用结构型指令时,需要把 * 去掉,并且用 [] 把星号后面的字符串包裹起来。上面来自官方的那一段代码对于 *ngFor 的处理也很好的印证了这一点,在转成 <ng-template> 的形式的时候也是这么处理的。所以我们可以像下面这样写:

<ul>
  <li *ngFor="let person of persons;let even = even">
    <ng-template [ngIf]="even">
      <p>{{person.name}} 今年 {{person.age}} 岁</p>
    </ng-template>
  </li>
</ul>

从上面的例子可以看出,<ng-container> 在 Angular 中的用法更接近原生的 DOM。所以以后在使用这两个 Angular 元素时得注意他们用法的不同,区别开来了,用起来就更加地爽快了。不知这里肯定会浪费一点时间去找原因。

在 select 下拉框中这两个标签就显得非常的有用了:

<select [(ngModel)]="selectPerson">
  <ng-container *ngFor="let person of persons">
    <ng-container *ngIf="person.age>12">
      <option [ngValue]="person">{{person.name}}( {{person.age}} 岁 )</option>
    </ng-container>
  </ng-container>
</select>

Angular 2+ 结构型指令就分享到这里。

  • 微信扫一扫,赏我

  • 支付宝扫一扫,赏我

声明

原创文章,不经本站同意,不得以任何形式转载,如有不便,请多多包涵!

本文永久链接:http://yunkus.com/angular-core-knowledge-structural-directives/

Leave a Reply

Your email address will not be published. Required fields are marked *

评论 END