使用相同表达式来评估多个指令的哪种方法合适? Angular的摘要周期使用数据定义可观察对象定义另一个可观察到的行业ID 合并两个selectedIdSubject$ = new BehaviorSubject<number>(1) // By default 1 will be selected selectedId$ = this.selectedIdSubject$.asObservable() 几乎完成,订阅结果rxjs/operators 最后...定义触发

问题描述

我目前正在构建一个表,该表具有一个特定的列,在该表中我需要进行一些数据处理以获得想要显示的实际值;该行对象中的值是一个ID号,因此我必须在变量中包含的对象数组中查找该ID。

赞:

findindustry(industry: string) {
if (this.industries.find(x => x._id === parseInt(industry,10))) {
  const industryResult = this.industries.find(x => x._id === parseInt(industry,10));
  return `${industryResult.category} | ${industryResult.subcategory}`;
}
  return '(Not Set)';
}

获得结果后,我可以将其显示在桌子上,如下所示:

<ng-container matColumnDef="parentName">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Industry </th>
      <td mat-cell *matCellDef="let client" class="industry-cell">{{ findindustry(client.industry) }}</td>
</ng-container>

但是现在问题来了;基于返回的值,我想显示一个title属性,并且我还想添加一个ngClass指令以当(Not Set)为值时以灰色显示文本:>

<ng-container matColumnDef="parentName">
     <th mat-header-cell *matHeaderCellDef mat-sort-header> Industry </th>
     <td mat-cell *matCellDef="let client"
         [ngClass]="findindustry(client.industry) === '(Not Set)' ? 'text-muted' : ''"
         class="industry-cell"
         [title]="findindustry(client.industry)">{{ findindustry(client.industry) }}</td>
</ng-container>

我读到在Angular模板中使用函数调用一个坏主意,因为它会在每次更改检测时运行该函数,这可能很多次;我想知道什么是避免多次运行该函数的有效方法,或者甚至更好的选择是根本避免使用该函数;我确实需要相同的值来应用不同的属性,这是我在每个指令和属性上使用它的唯一原因。

解决方法

我想做的是将其保存在一个大对象中,如下所示:

max

然后在您的模板中:

findIndustry() {
//
 this.object[x._id] =  `${industryResult.category} | ${industryResult.subcategory}`;
//
}

我希望它不是太抽象(如果您有实现stackblitz的实现会有所帮助)。

,

正如您所说,在html中具有函数是一个非常糟糕的主意...

下面是有关如何在html中调用函数的文章

Angular的摘要周期

摘要循环是Angular自动更新魔术的工作原理-这是在输入框中键入内容会自动更新任何涉及其值的内容的原因。

摘要循环运行时,它将有效地重画页面上可能已更改的所有内容。

Angular使用一些技巧来查找“可能已更改的所有内容”,而主要技术是观察者。当您使用ng-ifng-class之类的指令时,以及使用{{ yourBindingHere }}之类的绑定时,会自动创建这些观察程序。

这些东西中的每一个都注册了一个观察者。 运行Angular的摘要周期时,要求每个观察者更新其状态。对于ng-class,它将重新运行绑定到它的函数,以查看是否需要更改。 这就是您的控制器功能多次运行的原因,并且每次页面上的任何更改都会再次运行。
来源Controller Function Is Executed Multiple Times

应急救援程序

默认情况下,Angular预先安装了rxjs。我们可以利用Observables的力量来解决此问题。

我们可以实现类似

  • 用数据定义可观察对象
  • 定义另一个可观察到的行业ID
  • 合并两个Obsevables
  • 订阅结果Observable
  • 定义触发行业ID更改的方法

使用数据定义可观察对象

在许多情况下,这仅仅是来自http请求的响应

industries$ = this.http.get<IIndustries[]>('some/api')

我们还可以使用from的{​​{1}}和of运算符生成一个可观测值

rxjs

定义另一个可观察到的行业ID

下一步是定义一种跟踪所选行业的方法。我将使用一个industries: IIndustries[] = [{ ... },{ ... },...] industries$ = of(this.industries) ,它会在初始加载时以及每次在BehaviorSubject

上调用next()函数时发出一个值
Subject

合并两个selectedIdSubject$ = new BehaviorSubject<number>(1) // By default 1 will be selected selectedId$ = this.selectedIdSubject$.asObservable()

接下来,我们需要结合两个Obsevables。我们将使用Observables中的combineLatest 从官方文档中

当您有多个相互依赖的长寿命可观测对象进行某些计算或确定时,最好使用此运算符。
来源Why use combineLatest?

rxjs

我们正在传递industry$ = combineLatest([this.industries$,this.selectedId]).pipe( map(([industries,industry]) => { if (industries.find(x => x._id === parseInt(industry,10))) { const industryResult = industries.find(x => x._id === parseInt(industry,10)); return `${industryResult.category} | ${industryResult.subcategory}`; } return '(Not Set)'; } }) ) 流,并使用Observable中的map运算符来转换数据

几乎完成,订阅结果rxjs/operators

我们将通过Observable管道来实现此目的

async

最后...定义触发行业ID更改的方法

要触发所选项目的更改,我们只需在<ng-container matColumnDef="parentName"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Industry </th> <td mat-cell *matCellDef="let client" class="industry-cell">{{ industry$ | async }}</td> </ng-container>

上调用next方法
Subject

采用上述方法,只有在调用changeSelectedId (id) { this.selectedIdSubject$.next(id) } 函数时才会触发角度变化检测