角度-每次更改都重新计算一个变量

时间:2018-07-20 06:44:21

标签: javascript angular

我有一个变量,可以随时存储可用的汽车。有没有一种方法可以在每次更改时自动重新评估此功能?

在这种情况下仅使用this.carFactory.available不是解决方案,因为我正在演示的这个示例已简化-项目中的实际计算要复杂得多。

calculateAvailableCars(){
    this.carFactory.available.forEach(function(item){
      this.availableCars.push(car.id);
    }.bind(this));
}

我如何在Angular 2中做到这一点?在Angular JS中,可以$ watch一个函数。

我当然可以在每次更改时手动调用此函数,但是最好不必在应用程序的每个可以更改数据的部分调用此函数。

3 个答案:

答案 0 :(得分:2)

将模板功能参考与自动更改检测一起使用

您可以在模板上使用此函数输出:

carOutput(): cars[] {
  this.calculateAvailableCars()
  return this.availableCars;
}

并在模板上使用输出:

<p>My car ratio is {{ carOutput() }} </p>

但是,这将触发对该变量非常积极的更改检测策略。这个解决方案是最简单的,但是从工程角度来看却是最糟糕的:消耗大量不必要的函数调用。需要注意的是,必须设置主机元素才能检测到更改onPush

将数据模型与父组件分开,并作为属性传递给子组件

您可以将汽车列表显示存储在单独的组件中,并将新的汽车数组作为输入属性传递到此组件:

<car-display [cars]="availableCars"></car-display>

然后,您可以将此组件中的changeDetetcion策略设置为onPush,并且每次将绑定到availableCars的输入属性更改时,<car-display>将重新呈现。

如果更新在某些主机绑定上中继

如果某些外部主机操作触发了新车计算,那么hostBinding可能会有所帮助:

@hostListener(`hover`) recalculateCars() {
  this.calculateAvailableCars()
}

最后,(因为您用保密的方式描述了用例,没有太多细节,因此我正在讨论所有可能的方案)如果某些外部组件操作将触发重新计算,则可以使用ngLifecycle { {1}}例如,如果外部输入属性更改将重新触发汽车计算。

换句话说,所有这些加起来,取决于触发变更的人员和来源,然后重新触发可用的汽车重新计算。

非常重要,请参阅@ chiril.sarajiu的答案,因为我们在此处尝试解决的问题可以由单个可观察对象自动处理。这需要额外的设置(服务,例如可观察到的组件),但这是值得的。

---编辑---

如果每个变量更改都应重新触发数据

正如OP所阐明的那样,更改与绑定到组件的模型有关。因此,@ marvstar提到的另一个选项是使用ngOnChanges(),其中每个模型变量的更改都会重新触发获取函数:

set

答案 1 :(得分:1)

您需要RxJS。您要做的是创建一个数据服务,该数据服务将存储一个Observable(在我的情况下,是BehaviorSubject,这几乎是相同的,但在我的情况下,我从一个值开始)。

export class DataService {
  private dataStorage$ = new BehaviorSubject(null); //here is the data you start with

  get getDataStorage() {
     return this.dataStorage$.asObservable(); // so you won't be able to change it outside the service
  }

  set setDataStorage(data: any) {
    this.dataStorage$.next(data);
  }
}

然后,您订阅该数据的位置将发生变化,

constructor(private dataService: DataService){}
ngOnInit() {
  this.dataService.getDataStorage.subscribe((data) => this.calculateAvailableCars(data));
}
calculateAvailableCars(){
   this.carFactory.available.forEach(function(item){
     this.availableCars.push(car.id);
   }.bind(this));
}

阅读有关在Angular中使用RxJS的最佳实践的更多信息,因为可能会有很多陷阱和问题。

答案 2 :(得分:0)

尝试使用setter和getter。

private _YourVariable:any;

public set YourVariable(value:any){
this._YourVariable = value;
//do your logik stuff here like. calculateAvailableCars
}

public get YourVariable():any{
return this._YourVariable ;
}