2016-01-26 101 views
8

今天,我不得不修复由此引起的代码性能问题:注重updateStats称为模板中函数被调用多次(角JS)

<script type="text/ng-template" id="entityGrouper"> 

<section> 

<div> 
<ul ng-click="hideEntityBox = !hideEntityBox"> 
<li> 
{{ entityNode.name }} 
</li> 
<li ng-repeat="breadcrumbItem in entityNode.breadcrumb"> 
{{ breadcrumbItem }} 
</li> 
</ul> 
{{ updateStats(entityNode) }} 
<span ng-include="'/mypath/views/resume.html'"></span> 
</div> 

<div> 

<div ng-repeat="entityNode in entityNode.group" ng-include="'entityGrouper'"></div> 
<div ng-repeat="entity in entityNode.group" ng-include="'entityBox'"></div> 

</section> 

</script> 

模板使用:

<div ng-repeat="entityNode in entityNode.group" ng-include="'entityGrouper'"></div> 

调试完这段代码之后,我发现这个函数调用的时间比数组大小多(我的数组有4个对象,函数被调用超过100次),甚至鼠标悬停都称为此函数。 我解决了这个问题,只需在模板中放入一个ng-init,现在它工作正常,但我没有弄清楚为什么这个函数被调用了很多次。有两种数据绑定方式吗?

+0

你递归调用相同的模板?还有一个'

'内部模板 – Developer

回答

1

发生这种情况不是因为双向数据绑定(它可适用于形成输入),而是角度变化的检测,因为。 Angular定期检查绑定到模板的任何值是否更改,如果是,则更新其在视图中的值。通常,它由用户生成的事件触发。为了检查updateStats(entityNode)的值是否发生了变化,Angular会对它进行评估,这会导致性能下降。

若要解决此问题,您可以使用前面提到的一次性绑定updateStats(entityNode)如果结果设置一次并且将来不会更改。我想,这是你的情况,你已经将评估移至ng-init。对于随时间更新的值,最好在entityNode(如entityNode.stats)中创建单独的属性,将其显示在模板中,并仅在需要时在控制器或服务中运行updateStats(entityNode)。通过这样做,您将防止在每个摘要循环中运行updateStats(entityNode)(您已经看到了这种情况的频率),从而提高了应用程序的性能。

4

对于这样的场景,通常建议使用$watch。由于您绑定了一个函数{{updateStats()}},它将在每个摘要循环中执行。

因此,在您的代码中,每当调用摘要循环时,它也会调用该函数。消化周期在Angular中经常被内部调用。

+0

这个应该是被接受的正确答案 – thiagoh

2

你所看到的是消化循环的结果。

添加一个::将调用该函数一次/一次绑定。

{{ ::updateStats(entityNode) }}

+0

什么::正确地做? –

+1

'::'提供一次性绑定。如果你用这个前缀表达式,它将停止运行或在第一个摘要之后重新计算。更多信息* [文档](https://docs.angularjs.org/guide/expression)的一次性绑定*部分。 –