gpt4 book ai didi

javascript - Angular 性能 : ngStyle recalculates on each click on random input

转载 作者:太空狗 更新时间:2023-10-29 17:45:56 25 4
gpt4 key购买 nike

我有一个非常愚蠢的性能问题。

我有一个使用 ngStyle 的组件,我不想重写它。但每次我在同一页面上单击随机input(甚至来自另一个组件)时,ngStyle 都会重新计算(而且速度很慢)。

假设我想要一个具有动态背景的乘法表:

<section>
<div class="row"
*ngFor="let row of rows">
<div class="col"
[ngStyle]="{'background-color': getBG(row*col)}"
*ngFor="let col of cols ">
{{row * col}}
</div>
</div>
</section>

然后出于某种原因我想在同一页面上添加几个输入:

<section>
<input type="text" [ngModel]="model1"/>
<input type="text"[ngModel]="model2"/>
<input type="text"[ngModel]="model3"/>
<input type="text"[ngModel]="model4"/>
<input type="text"[ngModel]="model5"/>
</section>

现在每次我点击其中一个输入时 - getBG() 都会被调用。即使该函数只返回一个字符串而不进行任何计算——它仍然非常慢

Example at StackBlitz - 只需打开控制台并尝试在不同的输入字段之间快速单击,或输入一个值。即使作为用户,我也能看到它根本没有响应


UPD1:我的真实案例要复杂得多。并且已经使用了 ChangeDetectionStrategy.OnPush。将 ngStyle 绑定(bind)到一个值而不是函数也没有太大帮助 - 它更快但仍然很慢(并产生很多复杂性)。我想要的可能是一种告诉 ngStyle 在我明确询问之前不要重新计算的方法。也许 ChangeDetectorRef.detach() 可以提供帮助

最佳答案

这很有道理。这就是 Angular 执行变更检测的方式。这是 Angular 执行额外的检查,因为你在其中一种数据绑定(bind)语法中调用了一个函数,在这里:

[ngStyle]="{'background-color': getBG(row*col)}" 

Angular 在三种情况下执行变更检测:

  1. DOM 事件。
  2. AJAX 调用。
  3. 超时/间隔。

这就是 DOM 事件(点击)的情况。

现在,在执行变更检测时,Angular 会检查组件中的特定变量是否已更改。

在属性的情况下,这非常简单。但在函数的情况下就不那么直接了。

你看,判断一个函数的值是否改变的唯一方法就是调用它。

Angular 就是这样做的。

解决方案:

只需在组件类中为要显示的数字和要绘制的颜色创建一个矩阵:

import { Component } from '@angular/core';

@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
rows = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
cols = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
matrix = [];

model1 = '';
model2 = '';
model3 = '';
model4 = '';
model5 = '';

ngOnInit() {
this.rows.forEach((row, rowIndex) => {
this.matrix.push([]);
this.cols.forEach((col, colIndex) => {
const product = row * col;
this.matrix[row].push({
numberToShow: product,
color: this.getBG(product),
});
})
});
}

getBG(hue: number): string {
console.log('getBG was called');
return 'hsl(' + hue + ', 100%, 50%)';
}

}

然后在你的模板中使用它:

<br/>
<div> 1. Open a console</div>
<br/>

<section>
<div class="row" *ngFor="let row of matrix">
<div
class="col"
[style.background-color]="col.color"
*ngFor="let col of row ">
{{col.numberToShow}}
</div>
</div>
</section>

<br/>
<div>2. Click fast on the different inputs: </div>
<br/>

<section>
<input type="text" [ngModel]="model1"/>
<input type="text"[ngModel]="model2"/>
<input type="text"[ngModel]="model3"/>
<input type="text"[ngModel]="model4"/>
<input type="text"[ngModel]="model5"/>
</section>

性能差异:

在之前的实现中,getBG 在初始化时被调用了 401 次。

在解决方案实现中,getBG 在初始化时被调用了 101 次。

这是一个巨大的性能提升,大约 397%

此外,当用户从任何输入字段聚焦和模糊时,不会额外调用 getBG 方法。

Here's a Working Sample StackBlitz for your ref.

You might also want to read through a Medium Article that I wrote about Performant Reactive Forms in Angular. Although it's related to Reactive Forms, I've touched upon this aspect, in the article. I'm sure you'll find it helpful.

关于javascript - Angular 性能 : ngStyle recalculates on each click on random input,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57060232/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com