Angular 的 *ngFor 循环是如何实现的? [英] How is Angular's *ngFor loop implemented?
问题描述
我想知道 Angular 的 *ngFor
指令实际上是如何工作的?我想知道使用指令时发生的整个过程.
I wonder how does Angular's *ngFor
directive actually work under the hood? I would like to know the whole process that happens when I use the directive.
对于downvoters:我见过ng-for-of 文件,虽然没有单一用法传递给 *ngFor
数组的 eg我知道的 join()
方法被调用.谢谢您的支持 :)这是显示行为的 plunker:https://plnkr.co/edit/IXVxWrSOhLBgvSal6PWL?p=预览
For downvoters: I've seen the ng-for-of file, although there is no single usage of passed to *ngFor
array's e.g. join()
method that I know is invoked. Thanks for your support :)
Here is the plunker that shows the behavior: https://plnkr.co/edit/IXVxWrSOhLBgvSal6PWL?p=preview
推荐答案
这是一个高级概述.假设您像这样定义模板:
Here is a high level overview. Suppose you define your template like this:
<span *ngFor="let item of items">{{item}}</span>
然后它被编译器转换为以下内容:
Then it's transformed to the following by the compiler:
<ng-template let-item [ngForOf]="items">
<span>{{item}}</span>
</ng-template>
然后 Angular 将 ngForOf
指令应用于模板元素.由于该指令的宿主元素是模板,因此它注入了 templateRef
.它还注入了 viewContainerRef
作为锚元素,并将用于添加 DOM 元素:
Then Angular applies ngForOf
directive to the template element. Since this directive's host element is template, it injects the templateRef
. It also injects the viewContainerRef
that acts as an anchor element and will be used to add DOM elements alongside:
constructor(
private _viewContainer: ViewContainerRef,
private _template: TemplateRef<NgForOfContext<T>>,
该指令将 ngForOf
定义为输入,然后等待它初始化并创建一个不同的:
The directive defines ngForOf
as an input and then waits until it's initialized and creates a differ:
ngOnChanges(changes: SimpleChanges): void {
const value = changes['ngForOf'].currentValue;
this._differ = this._differs.find(value).create(this.ngForTrackBy);
然后在每个检查检测周期中,它使用此差异将值与之前的值进行比较:
Then on each check detection cycle it compares the values to the previous values using this differ:
ngDoCheck(): void {
if (this._differ) {
const changes = this._differ.diff(this.ngForOf);
if (changes) this._applyChanges(changes);
}
}
如果值改变了,它会应用改变做以下事情:
If the values changed, it applies the changes doing the the following things:
1) 为 items
context = new NgForOfContext<T>(null !, this.ngForOf, -1, -1)
2) 使用 templateRef
在此上下文中创建嵌入视图,该视图有效地在 DOM 中呈现新值
2) creates embedded view with this context using the templateRef
which effectively renders new value in the DOM
this._viewContainer.createEmbeddedView(
this._template, context , currentIndex);
3) 为上下文添加相关值
3) adds relevant values to context
viewRef.context.index = i;
viewRef.context.count = ilen;
viewRef.context.$implicit = record.item;`
现在,你的问题:
虽然它没有解释为什么例如在数组上调用 join() 方法传递给
although it doesn't explain why e..g join() method is invoked on array passed to
由函数 normalizeDebugBindingValue
调用 此处 因为您的应用程序在开发模式下运行:
It's called by the function normalizeDebugBindingValue
here because your application is running in the development mode:
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';
}
}
如果您启用生产模式,将不再调用此函数.检查plunker.
If you enable production mode, this function will no longer be called. Check the plunker.
这篇关于Angular 的 *ngFor 循环是如何实现的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!