当前位置: 首页 > 工具软件 > ng-deerway > 使用案例 >

ngFor

蒋高超
2023-12-01

在 angular2 里,我们介绍了一个新概念叫"structural directives",用来描述那些根据表达式在 DOM 上或增加、或删除元素的指令。和其他指令不同,"structural directive"要么作用在template tag上、 要么配合template attribute使用、要么前缀"*"作为简写语法糖。因为这个新语法特性,初学者常常犯错。

你能分辨出来以下错误么?

错误的 ngFor 用法

// a:
<div *ngFor="#item in items">
   <p> {{ item }} </p>
</div>

// b:
<template *ngFor #item [ngForOf]="items">
   <p> {{ item }} </p>
</template>

// c:
<div *ngFor="#item of items; trackBy=myTrackBy; #i=index">
   <p>{{i}}: {{item}} </p>
</div>

来,一步步解决错误

5a:把"in"换成"of"

// incorrect
<div *ngFor="#item in items">
   <p> {{ item }} </p>
</div>

如果有 AngularJS 1 经验,通常很容易犯这个错。在 AngularJS 1 里,相同的repeater写作 ng-repeat="item in items" 。

angular2 将"in"换成"of"是为了和ES6中的 for-of 循环保持一致。也需要记住的是,如果不用"*"语法糖,那么完整的repeater写法要写作 ngForOf , 而非 ngForIn

// correct
<div *ngFor="#item of items">
   <p> {{ item }} </p>
</div>

5b:语法糖和完整语法混着写

// incorrect
<template *ngFor #item [ngForOf]="items">
   <p> {{ item }} </p>
</template>

混着写是没必要的 - 而且事实上,这么写也不工作。当你用了语法糖(前缀"*")以后, angular2 就会把她当成一个template attribute,而不是一般的指令。具体来说,解析器拿到了 ngFor 后面的字符串, 在字符串前面加上 ngFor ,然后当作template attribute来解析。如下代码:

<div *ngFor="#item of items">

会被当成这样:

<div template="ngFor #item of items">

当你混着写时,他其实变成了这样:

<template template="ngFor" #item [ngForOf]="items">

从template attribute角度分析,发现template attribute后面就只有一个 ngFor ,别的什么都没了。那必然解析不会正确,也不会正常运行了。

如果从从template tag角度分析,他又缺了一个 ngFor 指令,所以也会报错。没了 ngFor 指令, ngForOf 都不知道该对谁负责了。

可以这样修正,要么去掉"*"写完整格式,要么就完全按照"*"语法糖简写方式书写

// correct
<template ngFor #item [ngForOf]="items">
   <p> {{ item }} </p>
</template>

// correct
<p *ngFor="#item of items">
   {{ item }}
</p>

5c:在简写形式里用了错误的操作符

// incorrect
<div *ngFor="#item of items; trackBy=myTrackBy; #i=index">
   <p>{{i}}: {{item}} </p>
</div>

为了解释这儿到底出了什么错,我们先不用简写形式把代码写对了看看什么样子:

// correct
<template ngFor #item [ngForOf]="items" [ngForTrackBy]="myTrackBy" #i="index">
   <p> {{i}}: {{item}} </p>
</template>

在完整形式下,结构还是很好理解的,我们来试着分解一下:

  • 我们通过输入属性向 ngFor 里传入了两组数据:

    • 绑定在 ngForOf 上的原始数据集合 items

    • 绑定在 ngForTrackBy 上的自定义track-by函数

  • 用 # 声明了两个 local template variables ,分别是: #i 和 #item 。 ngFor 指令在遍历 items 时,给这两个变量赋值

    • i 是从0开始的 items 每个元素的下标

    • item 是对应每个下标的元素

当我们通过"*"语法糖简写代码时,必须遵守如下原则,以便解析器能够理解简写语法:

  • 所有配置都要写在 *ngFor 的属性值里

  • 通过 = 操作符设置 local variable

  • 通过 : 操作符设置input properties

  • 去掉input properties里的 ngFor 前缀,譬如: ngForOf ,就只写成 of 就可以了

  • 用分号做分隔

按照上述规范,代码修改如下:

// correct
<p *ngFor="#item; of:items; trackBy:myTrackBy; #i=index">
   {{i}}: {{item}}
</p>

分号和冒号其实是可选的,解析器会忽略它们。写上仅仅是为了提高代码可读性。因此,也可以再省略一点点:

// correct
<p *ngFor="#item of items; trackBy:myTrackBy; #i=index">
   {{i}}: {{item}}
</p>
 类似资料: