问题描述
我目前正在构建一个表,该表具有一个特定的列,在该表中我需要进行一些数据处理以获得想要显示的实际值;该行对象中的值是一个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-if
和ng-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>
Subject
采用上述方法,只有在调用changeSelectedId (id) {
this.selectedIdSubject$.next(id)
}
函数时才会触发角度变化检测