ngFor
ngFor
在开发使用上已经是比较普遍了,这里主要介绍下一些通常不被关注的便捷用法
便捷用法
ngFor
不仅仅提供了 index
属性(索引属性),还提供了一些实用的对外属性,所有实用对外属性如下:
- index :元素索引
- first :是否为第一个元素
- last :是否为最后一个元素
- even :是否为偶数元素
- odd :是否为奇数元素
示例如下:
<li *ngFor="let item of list; index as i; first as isFirst; last as isLast; ...">
<span>Item's index is {{ i }}</span>
<span *ngIf="isFirst">First item</span>
<span *ngIf="isLast">Last item</span>
...
</li>
<!-- or -->
<li *ngFor="let item of list; let i = index; let isFirst = first; let isLast = last; ...">
<span>Item's index is {{ i }}</span>
<span *ngIf="isFirst">First item</span>
<span *ngIf="isLast">Last item</span>
...
</li>
源码注释
/**
* A [structural directive](guide/structural-directives) that renders
* a template for each item in a collection.
* The directive is placed on an element, which becomes the parent
* of the cloned templates.
*
* The `ngForOf` directive is generally used in the
* [shorthand form](guide/structural-directives#the-asterisk--prefix) `*ngFor`.
* In this form, the template to be rendered for each iteration is the content
* of an anchor element containing the directive.
*
* The following example shows the shorthand syntax with some options,
* contained in an `<li>` element.
*
* ```
* <li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>
* ```
*
* The shorthand form expands into a long form that uses the `ngForOf` selector
* on an `<ng-template>` element.
* The content of the `<ng-template>` element is the `<li>` element that held the
* short-form directive.
*
* Here is the expanded version of the short-form example.
*
* ```
* <ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn">
* <li>...</li>
* </ng-template>
* ```
*
* Angular automatically expands the shorthand syntax as it compiles the template.
* The context for each embedded view is logically merged to the current component
* context according to its lexical position.
*
* When using the shorthand syntax, Angular allows only [one structural directive
* on an element](guide/structural-directives#one-structural-directive-per-host-element).
* If you want to iterate conditionally, for example,
* put the `*ngIf` on a container element that wraps the `*ngFor` element.
* For futher discussion, see
* [Structural Directives](guide/structural-directives#one-per-element).
*
* @usageNotes
*
* ### Local variables
*
* `NgForOf` provides exported values that can be aliased to local variables.
* For example:
*
* ```
* <li *ngFor="let user of userObservable | async as users; index as i; first as isFirst">
* {{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span>
* </li>
* ```
*
* The following exported values can be aliased to local variables:
*
* - `$implicit: T`: The value of the individual items in the iterable (`ngForOf`).
* - `ngForOf: NgIterable<T>`: The value of the iterable expression. Useful when the expression is
* more complex then a property access, for example when using the async pipe (`userStreams |
* async`).
* - `index: number`: The index of the current item in the iterable.
* - `first: boolean`: True when the item is the first item in the iterable.
* - `last: boolean`: True when the item is the last item in the iterable.
* - `even: boolean`: True when the item has an even index in the iterable.
* - `odd: boolean`: True when the item has an odd index in the iterable.
*
* ### Change propagation
*
* When the contents of the iterator changes, `NgForOf` makes the corresponding changes to the DOM:
*
* * When an item is added, a new instance of the template is added to the DOM.
* * When an item is removed, its template instance is removed from the DOM.
* * When items are reordered, their respective templates are reordered in the DOM.
*
* Angular uses object identity to track insertions and deletions within the iterator and reproduce
* those changes in the DOM. This has important implications for animations and any stateful
* controls that are present, such as `<input>` elements that accept user input. Inserted rows can
* be animated in, deleted rows can be animated out, and unchanged rows retain any unsaved state
* such as user input.
* For more on animations, see [Transitions and Triggers](guide/transition-and-triggers).
*
* The identities of elements in the iterator can change while the data does not.
* This can happen, for example, if the iterator is produced from an RPC to the server, and that
* RPC is re-run. Even if the data hasn't changed, the second response produces objects with
* different identities, and Angular must tear down the entire DOM and rebuild it (as if all old
* elements were deleted and all new elements inserted).
*
* To avoid this expensive operation, you can customize the default tracking algorithm.
* by supplying the `trackBy` option to `NgForOf`.
* `trackBy` takes a function that has two arguments: `index` and `item`.
* If `trackBy` is given, Angular tracks changes by the return value of the function.
*
* @see [Structural Directives](guide/structural-directives)
* @ngModule CommonModule
* @publicApi
*/
ngFor 是什么
ngFor
是 Angular
自带的,便于开发的指令。这个指令做了什么呢?
ngFor
运用 Angular
中的 ng-template
标签(模板标签)进行遍历和渲染,最终呈现在视图上(这里只谈论 ngFor
因此忽略对 ng-template
的介绍,不明白 ng-template
是什么的可以将其理解为一种好看的瓷砖,想贴哪,就拿一块贴上 )
ngFor 与 DOM
在循环的过程中:
- 如果检测出有数据新增,就将
ngFor
的内容以DOM
的形式创建在页面上 - 如果检测出有数据减少,就将
ngFor
对应的DOM
节点从页面上移除 - 如果检测出顺序有变化,也将调整模板的顺序
ngFor 与 trackBy
由于默认的,ngFor
中遍历的东西发生任何变化,都将重新变更 ngFor
中的所有元素。而 trackBy
可以告诉视图,哪些变化的时候需要变更,以此来提高页面性能。trackBy
接收的是一个方法,有两个入参:index
和 item
。使用示例如下:
// 只有 item 的 name 属性发生变化的时候,才更新该 item 对应的模板视图
<li *ngFor="let item of list; trackBy: nameTracker;">{{ item.name }}</li>
nameTracker(index: number, item: any) {
return item.name;
}
ngFor 在 ng-template 上的使用方式
ngFor
在 ng-template
上的使用方式与页面元素标签上有所不同:
<ng-template ngFor let-item [ngForOf]="list" let-i="index" let-isLast="last" [ngForTrackBy]="trackByFn">
<span>Item's index is {{ i }}</span>
<span *ngIf="isLast">Last item</span>
</ng-template>
trackByFn(index: number, item: any) {
return index;
}
ngFor 与 $implicit
在 ngFor
中,默认的,$implicit
的值为 item
的值
$implicit
也是 ngFor
提供出的属性,ngFor
提供出该属性完全是因为 ngFor
的内部使用了 ng-template
,而 $implicit
是 ng-template
向模板内提供的内部上下文参数。若想详细了解 $implicit
,可以看一下 Angular
文档中关于 ng-template
相关教程