首页 > 解决方案 > 当 *ngIf 应用于表格以修复闪烁时 dataSource.sort 损坏

问题描述

关于角度 2 中的材料表。在我的 ngoni() 中,我有 this.mydatasource.sort = this.sort。排序有效,但在加载数据时,我短暂地看到表头(闪烁),然后出现整个表。一旦我做一个表 ngif="mytabledata" 标题闪烁消失,整个表的数据像我想​​要的那样立即出现,但现在排序不起作用,因为当它点击 ngoni 时,我的数据没有加载。(数据加载到输入参数更改时触发的 ngonchanges 上)。我该如何解决这个难题?

标签: javascriptangulartypescriptangular-material2

解决方案


请注意:您必须在摘要循环this.dataSource.sort = this.sort中包含一个setTimeout()来建立链接,没有它,@ViewChild(MatSort) sort: MatSort由于*ngIf.

ngOnChanges() {
    const ELEMENT_DATA1: PeriodicElement[] = [
      { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
      { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
      { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
      { position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
      { position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
      { position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
      { position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
      { position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
      { position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
      { position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },

    ];
    this.dataSource.data = ELEMENT_DATA1;

    console.log(this.sort) //undefined
    setTimeout(() => {
      console.log(this.sort) //not undefined
      this.dataSource.sort = this.sort; 
    })

  }

堆栈闪电战

https://stackblitz.com/edit/angular-table-sort-not-working-pv8yap?embed=1&file=app/table-sorting-example.ts


Digest Cycle 是在 AngularJS 时代定义的一个术语......有关更多信息,请参阅这个 SO 答案......相信它现在更常被称为Change Detection

Angular 定义了一个所谓的摘要循环的概念。这个循环可以被认为是一个循环,在这个循环中,Angular 检查所有 $scope 监视的所有变量是否有任何变化。因此,如果您在控制器中定义了 $scope.myVar 并且该变量被标记为被监视,那么您明确告诉 Angular 在循环的每次迭代中监视 myVar 上的更改。

Angular - 是什么触发了 2 路数据绑定的摘要循环?


请参阅此非 Angular 特定答案了解为什么setTmiout()有效。

浏览器几乎必须同时完成许多事情,其中​​之一就是执行 JavaScript。但是 JavaScript 经常使用的一件事是要求浏览器构建一个显示元素。这通常被认为是同步完成的(特别是当 JavaScript 不是并行执行时),但不能保证是这种情况,并且 JavaScript 没有明确定义的等待机制。

解决方案是“暂停”JavaScript 执行以让渲染线程赶上。这就是 setTimeout() 超时为 0 的效果。它就像 C 中的线程/进程 yield。虽然它似乎说“立即运行”,但它实际上让浏览器有机会完成一些非 JavaScript 的事情,这些事情在处理这段新的 JavaScript 之前一直在等待完成.

为什么 setTimeout(fn, 0) 有时有用?


总之

摘要循环/更改检测通常是指非 Angular 浏览器相关的任务,例如渲染视图项等......在这个例子中,你ngOnchange()没有等待由你*ngIf变为 true 创建的渲染线程在浏览器中完成。 .. 并试图在@ViewChild视图引用实际存在于 DOM 之前绑定它...

  • 原因一 console.log 未定义
  • 而另一个里面setTimeout()不是

将该行代码包装setTimeout()*ngIf.


推荐阅读