Angular 的 *ngFor 循环是如何实现的? [英] How is Angular's *ngFor loop implemented?

查看:24
本文介绍了Angular 的 *ngFor 循环是如何实现的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆