Angular 角度材质表绑定的行数比

Angular 角度材质表绑定的行数比,angular,angular-material,Angular,Angular Material,我在一张有棱角的材料桌子上表现很差。当我检查控制台时,我可以看到它多次绑定每一行,尽管我看不到是什么触发了它。我已经尽可能地简化了我的代码,我仍然看到了这个问题 共有257行,但记录到控制台中的计数为1542,这意味着每行似乎绑定了6次。应为每行调用一次格式化函数decimaltimehours。你知道为什么它会绑定这么多次吗 import {HttpClient} from '@angular/common/http'; import {EndPoints} from '../utils/en

我在一张有棱角的材料桌子上表现很差。当我检查控制台时,我可以看到它多次绑定每一行,尽管我看不到是什么触发了它。我已经尽可能地简化了我的代码,我仍然看到了这个问题

共有257行,但记录到控制台中的计数为1542,这意味着每行似乎绑定了6次。应为每行调用一次格式化函数decimaltimehours。你知道为什么它会绑定这么多次吗

import {HttpClient} from '@angular/common/http';
import {EndPoints} from '../utils/endPoints';
import {MarketMakerEntry} from '../types/MarketMakerEntry';
import {MatTableDataSource} from '@angular/material/table';

@Component({
  selector: 'app-market-maker',
  templateUrl: './market-maker.component.html',
  styleUrls: ['./market-maker.component.css']
})

export class MarketMakerComponent {
  count = 0;
  dataSource: MatTableDataSource<MarketMakerEntry>;
  title = 'test';
  displayedColumns: string[] = ['EstimatedTimeToBidFill'];

  constructor(private http: HttpClient) {
    http.get<MarketMakerEntry[]>(EndPoints.GET_MARKETS).subscribe((marketMakerEntries: MarketMakerEntry[]) => {
      console.log(marketMakerEntries.length);
      this.dataSource = new MatTableDataSource<MarketMakerEntry>(marketMakerEntries);
    });
  }

  decimalTimeToHours(value: number): string {
    console.log(this.count++);
    return String(value);
  }
}
从'@angular/common/http'导入{HttpClient};
从“../utils/EndPoints”导入{EndPoints};
从“../types/MarketMakerEntry”导入{MarketMakerEntry};
从“@angular/material/table”导入{MatTableDataSource};
@组成部分({
选择器:“应用程序做市商”,
templateUrl:“./market maker.component.html”,
styleURL:['./market-maker.component.css']
})
导出类MarketMakerComponent{
计数=0;
数据源:MatTableDataSource;
标题=‘测试’;
displayedColumns:string[]=['EstimatedTimeToBidFill'];
构造函数(专用http:HttpClient){
http.get(EndPoints.get_MARKETS).subscribe((marketMakerEntries:MarketMakerEntry[])=>{
console.log(marketMakerEntries.length);
this.dataSource=新MatTableDataSource(marketMakerEntries);
});
}
分米小时(值:数字):字符串{
console.log(this.count++);
返回字符串(值);
}
}

ET标书填写
{{decimalTimeToHours(element.EstimatedTimeToBidFill)}

您的
decimaltimehours
方法被调用如此多次的原因与角度变化检测的工作原理有关。Angular跟踪HTML模板中的任何绑定,并在基础值更改时更新浏览器dom。但是,这不是一个神奇的过程。为了知道基础值何时更改,Angular必须手动检查这些值是否已更改。它获取当前值,并将其与为该绑定看到的最后一个值进行比较。如果该值更改,它将更新dom。如何以及何时运行此检测过程的更详细信息是一个巨大的主题。不过,重要的一点是,当更改检测运行时(似乎发生了6次),它将转到您的绑定以获取当前值

问题源于您在模板中使用了一个函数。每次更改检测想要计算值时,它都必须调用该函数以确定值(每次都创建一个新字符串),然后将其与旧字符串进行比较。这不是一个大问题,但这是一个你可以很容易避免的问题。一种解决方案是使用角度管道以您希望在表中看到的方式格式化数据:

<td mat-cell *matCellDef="let element"> {{element.EstimatedTimeToBidFill | decimalTimeToHoursPipe}}</td>
{{element.EstimatedTimeToBidFill | decimalTimeToHoursPipe}
Angular在这里很聪明,知道只在值更改时调用管道函数。您甚至可能不需要创建自定义管道。请查看随附的角形:


您可能会遇到的另一个问题是“我可以减少更改检测运行的次数吗?”。答案是肯定的。您可以研究将组件的
ChangeDetectionStrategy
设置为
OnPush
。一些信息。另外,要知道Angular会在开发模式中运行额外的更改检测周期,以检查您是否在不合适的时间分配模板引用的变量方面做了一些不好的事情。但是,当您为部署进行prod构建时,这种情况将不再发生,您的应用程序将获得轻微的性能提升。

非常感谢。这是一个非常好的答案,你完全抢先回答了我进一步的问题。我已经与AngularJS合作了很长一段时间,我知道变更检测已经取代了摘要周期,但我需要了解它是如何工作的。在我的一生中,我无法计算出什么会导致行被计算6次,因为我已经将代码剥离为仅绑定表。我会深入挖掘并解决它。再次感谢!不客气!您将看到,在渲染视图后,有许多事情会触发更改检测。这包括鼠标单击事件或xhr请求完成。确认这一点与变更检测相关的一种方法是,随着时间的推移,当您与应用程序交互时(当然是在您更改变更检测策略之前),您的功能将继续被调用。我总是发现在浏览器中呈现大型表的速度惊人地慢。
<td mat-cell *matCellDef="let element"> {{element.EstimatedTimeToBidFill | decimalTimeToHoursPipe}}</td>