【问题标题】:How does Angular2+ ngFor directive iterate over the ref iterable?Angular2+ ngFor 指令如何遍历 ref iterable?
【发布时间】:2019-05-22 00:52:54
【问题描述】:

我试图了解 Angular 的 *ngFor 指令是如何在幕后工作的。 我想知道的是,传递给指令的可迭代对象是否在每次循环迭代时被解释(如 JS for 循环的条件),或者 Angular 是否创建了一个具有该值的“缓存”类变量。为了回答这个问题,我做了一个ngFor,它有一个方法返回一个数组作为可迭代对象。

<li *ngFor="let data of test(dataArr)">{{data}}</li>

相关的 TS:

 dataArr = [1,2,3,4];
 iterationNb = 1;
 test(arr) {
    console.log('has iterated', this.iterationNb++);
    return arr.filter(i => true);
 }

这是我在控制台中得到的:

has iterated 1
has iterated 2
has iterated 3
has iterated 4

如果您需要 Angular 项目,这里是我用于试用的示例应用程序:https://stackblitz.com/edit/angular-3kmyyw

太好了,我看到 angular 只是在每次迭代时调用该方法。但这对我来说开始变得复杂......

然后我尝试通过在其中添加一些其他值来更改该方法使用的引用数组dataArr

dataArr = [1,2,3,4,5,6,7];

但现在我的控制台中仍然有 4 次迭代... 然后我尝试了

dataArr = [1,2];

还有 4 次迭代……

所以现在我对此感到非常困惑...... 为什么我总是有 4 次迭代?第一次尝试只是幸运地在我的数组中选择了 4 个项目,实际上与此无关? 我试图查看 angular ngfor 源代码,但我仍然不是那种无需解释就能理解它的忍者……

谢谢

【问题讨论】:

  • 我试过你的 stackblitz,它显示了超过 4 次迭代

标签: angular loops ngfor angular2-changedetection


【解决方案1】:

太好了,我看到 angular 只是在每次迭代时调用该方法。但这对我来说开始变得复杂......

您没有看到迭代。每次渲染 DOM 时,Angular 都会调用该方法。它与数组中有多少元素无关。你看到它数到 4 只是运气。

<li *ngFor="let data of test(dataArr)">

上述内容在每个渲染过程中执行一次。 *ngFor 指令将表达式分解为两个变量。对 current 可迭代对象的引用,以及对源 iterator 的引用。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Iterators

ngFor 只需要在每次渲染过程中分配一次源iterator。在您的表达式中,test() 函数返回迭代器(恰好是一个数组)。它将从迭代器中获取 next() 值并将其分配给将在模板中公开的data 变量。

ngFor 将继续调用 next() 直到它到达迭代器的末尾。对于每次迭代,ngFor 检查是否存在应该插入、更新或删除的 DOM 元素。它使用 trackBy 函数知道哪些数据与哪个 DOM 元素对应。

https://medium.com/@ramy_ali/improving-angular-ngfor-performance-through-trackby-ae4cf943b878

【讨论】:

  • 可以看到this stackblitz中视图更新时只调用了一次该方法,这里关闭了自动变化检测,每4秒触发一次手动变化检测。
  • 感谢您的回答。您能否还解释一下为什么需要 4 次渲染,正如您所说的 once per rendering pass 并且根据我的理解,如果摘要周期没有注意到一些变化,则只有 1 次渲染。发送
  • @ylerjen 每次 zone 在 Web 浏览器中检测到异步事件时,它都会触发 Angular 更改检测。组件的默认行为是“CheckAlways”,这意味着 Angular 必须检查它是否发生了变化。如果您切换到 ChangeDetectionStrategy.OnPush,则组件仅检查其输入是否已更改。 netbasal.com/…
【解决方案2】:

这里有更多关于迭代器是什么的内容。数组是一个迭代器,但它是隐式的、自动的,你看不到它。您计算的不是事物被迭代了多少次,而是您的函数被调用了多少次

如果您想跟踪您有多少次迭代,您必须构建一个自定义迭代器。迭代器需要返回一个next() 方法,该方法被调用的次数与您要返回的值一样多。你从这个next() 返回的是一个带有{ value, done } 签名的对象——value 是任何东西,当你完成时done 是真的。在next 中,您可以计算迭代次数。

Here's 代码旁边的示例。

JavaScript 引擎的作用是隐式地使数组可迭代。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-13
    • 2019-10-27
    • 2016-05-23
    • 2017-06-02
    • 2023-03-09
    相关资源
    最近更新 更多