Angular的*ngFor循环是如何实现的?
How is Angular's *ngFor loop implemented?
我想知道 Angular 的 *ngFor
指令实际上是如何工作的?我想知道使用该指令时发生的整个过程。
对于投票者:我看过ng-for-of文件,虽然没有单独使用 passed to *ngFor
array's e.g. join()
调用了我知道的方法。谢谢您的支持 :)
这是显示行为的插件:https://plnkr.co/edit/IXVxWrSOhLBgvSal6PWL?p=preview
这是一个高级概述。假设您这样定义模板:
<span *ngFor="let item of items">{{item}}</span>
然后编译器将其转换为:
<ng-template let-item [ngForOf]="items">
<span>{{item}}</span>
</ng-template>
然后 Angular 将 ngForOf
指令应用于模板元素。由于此指令的宿主元素是模板,因此它会注入 templateRef
。它还注入充当锚元素的 viewContainerRef
并将用于在旁边添加 DOM 元素:
constructor(
private _viewContainer: ViewContainerRef,
private _template: TemplateRef<NgForOfContext<T>>,
该指令将 ngForOf
定义为输入,然后等待它初始化并创建一个不同的:
ngOnChanges(changes: SimpleChanges): void {
const value = changes['ngForOf'].currentValue;
this._differ = this._differs.find(value).create(this.ngForTrackBy);
然后在每个检查检测周期中,它使用此差异将值与先前的值进行比较:
ngDoCheck(): void {
if (this._differ) {
const changes = this._differ.diff(this.ngForOf);
if (changes) this._applyChanges(changes);
}
}
如果值发生更改,它会应用更改并执行以下操作:
1) 为 items
中的每个项目生成嵌入式视图上下文
context = new NgForOfContext<T>(null !, this.ngForOf, -1, -1)
2) 使用 templateRef
使用此上下文创建嵌入式视图,它有效地在 DOM
中呈现新值
this._viewContainer.createEmbeddedView(
this._template, context , currentIndex);
3) 将相关值添加到上下文
viewRef.context.index = i;
viewRef.context.count = ilen;
viewRef.context.$implicit = record.item;`
现在,你的问题:
although it doesn't explain why e..g join() method is invoked on array
passed to
它被函数 normalizeDebugBindingValue
here 调用,因为您的应用程序 运行 处于开发模式:
function normalizeDebugBindingValue(value: any): string {
try {
// Limit the size of the value as otherwise the DOM just gets polluted.
return value != null ? value.toString().slice(0, 30) : value;
^^^^^^^^^^^^^^^
} catch (e) {
return '[ERROR] Exception while trying to serialize the value';
}
}
如果启用生产模式,将不再调用此函数。检查 the plunker.
我想知道 Angular 的 *ngFor
指令实际上是如何工作的?我想知道使用该指令时发生的整个过程。
对于投票者:我看过ng-for-of文件,虽然没有单独使用 passed to *ngFor
array's e.g. join()
调用了我知道的方法。谢谢您的支持 :)
这是显示行为的插件:https://plnkr.co/edit/IXVxWrSOhLBgvSal6PWL?p=preview
这是一个高级概述。假设您这样定义模板:
<span *ngFor="let item of items">{{item}}</span>
然后编译器将其转换为:
<ng-template let-item [ngForOf]="items">
<span>{{item}}</span>
</ng-template>
然后 Angular 将 ngForOf
指令应用于模板元素。由于此指令的宿主元素是模板,因此它会注入 templateRef
。它还注入充当锚元素的 viewContainerRef
并将用于在旁边添加 DOM 元素:
constructor(
private _viewContainer: ViewContainerRef,
private _template: TemplateRef<NgForOfContext<T>>,
该指令将 ngForOf
定义为输入,然后等待它初始化并创建一个不同的:
ngOnChanges(changes: SimpleChanges): void {
const value = changes['ngForOf'].currentValue;
this._differ = this._differs.find(value).create(this.ngForTrackBy);
然后在每个检查检测周期中,它使用此差异将值与先前的值进行比较:
ngDoCheck(): void {
if (this._differ) {
const changes = this._differ.diff(this.ngForOf);
if (changes) this._applyChanges(changes);
}
}
如果值发生更改,它会应用更改并执行以下操作:
1) 为 items
context = new NgForOfContext<T>(null !, this.ngForOf, -1, -1)
2) 使用 templateRef
使用此上下文创建嵌入式视图,它有效地在 DOM
this._viewContainer.createEmbeddedView(
this._template, context , currentIndex);
3) 将相关值添加到上下文
viewRef.context.index = i;
viewRef.context.count = ilen;
viewRef.context.$implicit = record.item;`
现在,你的问题:
although it doesn't explain why e..g join() method is invoked on array passed to
它被函数 normalizeDebugBindingValue
here 调用,因为您的应用程序 运行 处于开发模式:
function normalizeDebugBindingValue(value: any): string {
try {
// Limit the size of the value as otherwise the DOM just gets polluted.
return value != null ? value.toString().slice(0, 30) : value;
^^^^^^^^^^^^^^^
} catch (e) {
return '[ERROR] Exception while trying to serialize the value';
}
}
如果启用生产模式,将不再调用此函数。检查 the plunker.