ngFor

来源:互联网 发布:怎样免费开淘宝网店 编辑:程序博客网 时间:2024/06/05 15:11

在 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>