奇怪的更新行为:模板不断调用显示功能

时间:2018-12-12 19:42:09

标签: angular typescript

我注意到一个奇怪的行为。如果我有一个具有inputfocus回调的focusout,则嵌套组件只有一个简单的类似于displaySomething的方法,就会被调用太多次。

仅看一下this stackblitz示例(请注意控制台中的日志消息)。

特别是

中的displayDataContent()
<div>
  <ul>
    <li *ngFor="let content of data.contents">
      {{ displayDataContent(content) }}
    </li>
  </ul>
</div>

为什么这个函数被调用那么多次?如果我之前没有在其中放置console.log语句,我不会注意到这种行为。

如何避免这种情况?我不明白为什么会首先发生这种情况。

1 个答案:

答案 0 :(得分:1)

这是预期的行为。这是绑定到模板的数据,并且Angular的更改检测周期检查绑定的属性,以查看其值是否已更改,并且需要在组件或其视图中进行更新。由于这是一种方法,因此Angular可以检查其值是否已更改的唯一方法是调用它,并将新结果与当前值进行比较。

在许多文章中,您经常会看到这种行为被认为是不好的做法,因为多个半昂贵的方法调用会严重损害页面的速度。但是,一种非常简单的方法几乎不需要计算就可以返回一个值,与使用getter或本机值访问器几乎没有什么不同,因此这种做法并不总是错误的……但是,它仍然(稍微)在堆栈上进行更多工作,并将阻止更改检测,直到方法完成。

由于这个原因,通常被认为是最佳方法,或者在绑定之前将值取消包装到组件属性,或者使用管道。如果值将由于组件外部的事件而改变,则使用Observableasync管道的Observable是最可取的模式。 ChangeDetectorRef的排放意味着检测到反应性变化,而不是轮询。

您还可以策略性地告诉Angular关闭或限制整个组件的变更检测,然后在需要时使用gulp.src([ // vendor folder first path.join(folder, '/vendor/**/*.js'), // custom js after vendor path.join(folder, '/**/*.js') ]) 手动运行变更检测周期...虽然这总体上可以加速变更检测是Angular作为框架最吸引人的事情之一,通常是将控件转换为Angular的更好的设计选择。