为什么这个 method/gettor 在 Angular 2 服务中被调用 X 次
Why does this method/gettor get called X times in an Angular 2 service
我正在尝试将 HTML 组件中的值绑定到服务中的 属性。如果私有变量为空,则它需要关闭并从 HTTP 调用中获取值。
但是,我注意到一旦我绑定到 HTML 组件中的 属性 gettor,它就会触发多次。
我已经简化了这个例子:
this Plunker
get Item(): string {
console.log("Item()", this._item);
return this._item;
}
打开控制台并观察 "Item() Initiated" 的多个输出。我希望它只会被击中一次。 (结果与方法而不是 gettor 相同)。如果我在点击方法中使用 Gettor,它只会触发一次。
这是因为 html 上绑定的值必须在应用程序中每次 "has changed" 时进行评估,这样如果绑定项的值发生变化,它将反映到html,从而为您提供这种神奇的自动更新绑定。这可能是您在 90% 的情况下想要的,因为您不想担心通知 angular 更新绑定 属性 的值。
话虽如此,如果您在 getter 中有一些繁重的逻辑,或者您更喜欢控制值何时更新,您可以将组件 changeDetectionStrategy 更改为 onPush,例如 in this plunker。
@Component({
selector: 'my-app',
template: `
<div><button (click)="_service.ShowItem()">Show Item</button></div>
<div>{{_service.Item}}</div>
`,
providers: [ Service ],
changeDetection: ChangeDetectionStrategy.OnPush
})
很好地解释了 angular2 变化检测的工作原理
这就像在说,"do not check this component when doing change detection, I will let you know when to check it"。
然后您可以使用名为 ChangeDetectorRef 的服务来标记组件以进行更改检测。
对于 http,你想要做的是有一个触发器来执行 http 调用,然后从响应中获取你需要的值,"cache" 它在某个地方,这样你就可以将它绑定到 UI.根据您的情况,触发器可以是多种多样的,例如。间隔、递归、按钮等
被接受的答案很棒,并且非常清楚地解释了一切。然而,就像他在 90% 的时间里所说的那样,您不会想要更改更改检测方法。因此,我有一个简单但丑陋的解决方法,我想当您访问数据库以获取一些数据并且不想连续多次点击 API 时我会分享。它将 return 一个空对象,直到数据下来。确保根据需要在模板上使用 *ngIf。
private __itemHit: number = 0;
private __item: string;
get Item(): string {
if(!this.__item && this.__itemHit == 0){
this.__itemHit = 1;
//Your data fetch is likely different than the way I do mine.
apiService.Post(url, body, option).subscribe((response) => { this.__item = response.Result;});
console.log("Item()", this._item);
}
return this._item;
}
我正在尝试将 HTML 组件中的值绑定到服务中的 属性。如果私有变量为空,则它需要关闭并从 HTTP 调用中获取值。
但是,我注意到一旦我绑定到 HTML 组件中的 属性 gettor,它就会触发多次。
我已经简化了这个例子: this Plunker
get Item(): string {
console.log("Item()", this._item);
return this._item;
}
打开控制台并观察 "Item() Initiated" 的多个输出。我希望它只会被击中一次。 (结果与方法而不是 gettor 相同)。如果我在点击方法中使用 Gettor,它只会触发一次。
这是因为 html 上绑定的值必须在应用程序中每次 "has changed" 时进行评估,这样如果绑定项的值发生变化,它将反映到html,从而为您提供这种神奇的自动更新绑定。这可能是您在 90% 的情况下想要的,因为您不想担心通知 angular 更新绑定 属性 的值。
话虽如此,如果您在 getter 中有一些繁重的逻辑,或者您更喜欢控制值何时更新,您可以将组件 changeDetectionStrategy 更改为 onPush,例如 in this plunker。
@Component({
selector: 'my-app',
template: `
<div><button (click)="_service.ShowItem()">Show Item</button></div>
<div>{{_service.Item}}</div>
`,
providers: [ Service ],
changeDetection: ChangeDetectionStrategy.OnPush
})
很好地解释了 angular2 变化检测的工作原理
这就像在说,"do not check this component when doing change detection, I will let you know when to check it"。
然后您可以使用名为 ChangeDetectorRef 的服务来标记组件以进行更改检测。
对于 http,你想要做的是有一个触发器来执行 http 调用,然后从响应中获取你需要的值,"cache" 它在某个地方,这样你就可以将它绑定到 UI.根据您的情况,触发器可以是多种多样的,例如。间隔、递归、按钮等
被接受的答案很棒,并且非常清楚地解释了一切。然而,就像他在 90% 的时间里所说的那样,您不会想要更改更改检测方法。因此,我有一个简单但丑陋的解决方法,我想当您访问数据库以获取一些数据并且不想连续多次点击 API 时我会分享。它将 return 一个空对象,直到数据下来。确保根据需要在模板上使用 *ngIf。
private __itemHit: number = 0;
private __item: string;
get Item(): string {
if(!this.__item && this.__itemHit == 0){
this.__itemHit = 1;
//Your data fetch is likely different than the way I do mine.
apiService.Post(url, body, option).subscribe((response) => { this.__item = response.Result;});
console.log("Item()", this._item);
}
return this._item;
}