简体   繁体   English

如何从模板中调用一次函数?

[英]How to call a function from a template exactly once?

I use a function call inside an angular2 template. 我在angular2模板中使用函数调用。 The function itself performs a http network request using http.get(), and returns an Observable of any[] that is actually a css style object: 函数本身使用http.get()执行http网络请求,并返回实际上是css样式对象的任何[]的Observable:

@Component({
    selector: "test-component",
    template: `<div *ngFor="let item of items" [ngStyle]="lookupStyle(item)"; }} </div>",
})
@Injectable()
export class TestComponent {

    @Input()
    items: Array<any>; 

    lookupStyle(params: any): Observable<any> {
        return this.http.get(/* ... */).map(/* ... */);
    }

    constructor(private http: Http) {}
}

But the above code will trigger an infinite loop ! 但是上面的代码会触发无限循环 The function lookupStyle is evaluated every time angular2 change detection takes place. 每次进行角度2变化检测时,都会评估函数lookupStyle Since http.get() will trigger a change-detection run, the function lookupStyle is re-evaluated after the http request complete - there is your infinite loop. 由于http.get()将触发更改检测运行,因此在http请求完成后重新评估函数lookupStyle - 存在无限循环。

Is there a solution or a better way in which i could tell angular to evaluate the function lookupStyle only once? 有没有解决方案或更好的方式,我可以告诉角度只评估函数lookupStyle一次? Now, I know I could probable come up with some .zip/.combineLatest magic on my viewmodel, but this seems overkill and would prodouce a lot of additional code - thats why I am looking for a better way. 现在,我知道我可能会在我的viewmodel上找到一些.zip/.combineLatest魔法,但是这看起来有点过分并会产生很多额外的代码 - 这就是为什么我在寻找更好的方法。

If you really only want it to run once, then this should do the trick: 如果你真的只想让它运行一次,那么这应该可以解决问题:

hasBeenRun: boolean = false;
@Component({
    selector: "test-component",
    template: `<div *ngFor="let item of items" [ngStyle]="lookupStyle(item)"; }} </div>",
})
@Injectable()
export class TestComponent {

    @Input()
        items: Array<any>; 

        lookupStyle(params: any): Observable<any> {
            if(!this.hasBeenRun){
                this.hasBeenRun = true;
                return this.http.get(/* ... */).map(/* ... */);
            }
        }
}
constructor(private http: Http) {}

hasBeenRun would need to be set back to false elsewhere for if you want it to be called again. hasBeenRun需要在其他地方设置为false,如果你想再次调用它。 Hopefully this is what you were looking for, though I also side with ngOnInit() being a very viable solution. 希望这是你正在寻找的,虽然我也支持ngOnInit()是一个非常可行的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM