函数被调用多次
function gets called several times
我想显示一个dataList。有些值是从函数计算得出的。 angular2 似乎多次调用计算函数。
<tr *ngFor="let data of dataList">
<td>{{ data.no }}</td>
<td>{{ data.name }}</td>
<td>{{ calculateFunction(data.price) }}</td>
</tr>
控制台会输出"calculate..."多次,超过dataList.length.
calculateFunction() {
console.log('calculate...');
return ...;
}
我应该担心性能问题还是让 angular2 这样做?
每次 Angular 运行 组件的更改检测(更准确地说是 ngFor
创建的嵌入视图)都会调用 caculateFunction(data.price)
函数。这是因为更新 DOM 是变更检测的一部分,而 Angular 需要调用 caculateFunction
来了解要用于 DOM 更新的值。而且变化检测周期可以 运行 相当频繁。因此,如果您在列表中有 3 个项目并且 CD 最初被触发了 3 次,您将看到该函数被调用了 9 次。
如果您检查 updateRenderer 函数,您应该会看到以下内容:
function(_ck,_v) {
var _co = _v.component;
var currVal_0 = _co.calculateFunction(_v.context.$implicit);
_ck(_v,3,0,currVal_0);
}
详细了解 Angular 如何在 The mechanics of DOM updates in Angular 中更新 DOM。
Should I worry about that for performance or just let angular2 do
this?
如果 calculateFunction(data.price)
returns 以相同的价格获得相同的结果,最好事先为每个项目计算这些值,然后简单地在模板中渲染它们。
<td>{{ data.no }}</td>
<td>{{ data.name }}</td>
<td>{{ data.calculatePrice) }}</t
通过这种方式,您将避免性能下降的函数调用。
您可以将组件 changeDetectionStrategy 更改为 onPush。之后,您的 calculateFunction 函数不会调用多次。
这样做 :
在您的组件中:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush // this line
})
export class AppComponent {
....
calculateFunction(value) {
console.log('calculate...');
return ...;
}
}
在你的 app.component.html 中:
<tr *ngFor="let data of dataList">
<td>{{ data.no }}</td>
<td>{{ data.name }}</td>
<td>{{ calculateFunction(data.price) }}</td>
</tr>
已更新
处理这种情况的最佳方法是使用 Pipe
,如下所示:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'handlePrice'
})
export class HandlePricePipe implements PipeTransform {
transform(price: number): number {
console.log('In Pipe ....');
return price * 2;
}
}
然后使用那个:
<tr *ngFor="let data of dataList">
<td>{{ data.no }}</td>
<td>{{ data.name }}</td>
<td>{{ data.price |handlePrice }}</td>
</tr>
@Component({
.
.
changeDetection: ChangeDetectionStrategy.OnPush // this line
})
export class MyComponent {
}
为组件装饰器添加变更检测解决了我的问题。
我想显示一个dataList。有些值是从函数计算得出的。 angular2 似乎多次调用计算函数。
<tr *ngFor="let data of dataList">
<td>{{ data.no }}</td>
<td>{{ data.name }}</td>
<td>{{ calculateFunction(data.price) }}</td>
</tr>
控制台会输出"calculate..."多次,超过dataList.length.
calculateFunction() {
console.log('calculate...');
return ...;
}
我应该担心性能问题还是让 angular2 这样做?
每次 Angular 运行 组件的更改检测(更准确地说是 ngFor
创建的嵌入视图)都会调用 caculateFunction(data.price)
函数。这是因为更新 DOM 是变更检测的一部分,而 Angular 需要调用 caculateFunction
来了解要用于 DOM 更新的值。而且变化检测周期可以 运行 相当频繁。因此,如果您在列表中有 3 个项目并且 CD 最初被触发了 3 次,您将看到该函数被调用了 9 次。
如果您检查 updateRenderer 函数,您应该会看到以下内容:
function(_ck,_v) {
var _co = _v.component;
var currVal_0 = _co.calculateFunction(_v.context.$implicit);
_ck(_v,3,0,currVal_0);
}
详细了解 Angular 如何在 The mechanics of DOM updates in Angular 中更新 DOM。
Should I worry about that for performance or just let angular2 do this?
如果 calculateFunction(data.price)
returns 以相同的价格获得相同的结果,最好事先为每个项目计算这些值,然后简单地在模板中渲染它们。
<td>{{ data.no }}</td>
<td>{{ data.name }}</td>
<td>{{ data.calculatePrice) }}</t
通过这种方式,您将避免性能下降的函数调用。
您可以将组件 changeDetectionStrategy 更改为 onPush。之后,您的 calculateFunction 函数不会调用多次。
这样做 :
在您的组件中:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush // this line
})
export class AppComponent {
....
calculateFunction(value) {
console.log('calculate...');
return ...;
}
}
在你的 app.component.html 中:
<tr *ngFor="let data of dataList">
<td>{{ data.no }}</td>
<td>{{ data.name }}</td>
<td>{{ calculateFunction(data.price) }}</td>
</tr>
已更新
处理这种情况的最佳方法是使用 Pipe
,如下所示:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'handlePrice'
})
export class HandlePricePipe implements PipeTransform {
transform(price: number): number {
console.log('In Pipe ....');
return price * 2;
}
}
然后使用那个:
<tr *ngFor="let data of dataList">
<td>{{ data.no }}</td>
<td>{{ data.name }}</td>
<td>{{ data.price |handlePrice }}</td>
</tr>
@Component({
.
.
changeDetection: ChangeDetectionStrategy.OnPush // this line
})
export class MyComponent {
}
为组件装饰器添加变更检测解决了我的问题。