typescript 如何通过 http 请求强制使用 Observables 在 nativescript(打字稿)上“刷新”UI?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37334677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to force UI "refresh" on nativescript (typescript) with Observables throught http requests?
提问by Richard Lee
I'm using a TabView component with template syntax to iterate over it and add items inside (using an observable collection and async pipe). My items come from a http request.
我正在使用带有模板语法的 TabView 组件来迭代它并在其中添加项目(使用可观察集合和异步管道)。我的项目来自一个 http 请求。
My home.component.tns.html as follows:
我的 home.component.tns.html 如下:
<ActionBar title="Angular 2 Seed Advanced (nativescript)">
</ActionBar>
<StackLayout>
<TabView selectedIndex="0" selectedColor="#FF0000">
<template ngFor let-tab [ngForOf]="tabs | async">
<StackLayout *tabItem="tab">
<Label text="tab item"></Label>
</StackLayout>
</template>
</TabView>
<Button text="call something" (tap)="emptymethod()"></Button>
</StackLayout>
...and my home.component.ts:
...还有我的 home.component.ts:
...
export class HomeComponent{
public tabs: Observable<any[]>;
constructor(private _menuService: MenuService) {
this._menuService.getMenu()
.map((menus) => {
let result: Array<any> = [];
if (menus) {
menus.forEach(menu => {
result.push({ 'title': menu.title });
});
}
return result;
})
.subscribe(
data => {
this.tabs = Observable.of<any[]>(data);
},
error => error => this._log.debug(error));
}
emptymethod() {
this._log.debug('HomeComponent - nada invoked');
}
ngOnInit() {
}
...
When the interface is renderized, the TabView menu does not appears, but when i click over call somethingbutton and emptymethodis called the items inside the TabView appears, in other words, after the "refresh" that component appears...
当界面被渲染时,TabView 菜单不会出现,但是当我点击调用某个按钮并调用空方法时,TabView中的项目出现,换句话说,在“刷新”该组件出现之后......
This should not happens automatically?
这不应该自动发生吗?
回答by Denko Mancheski
I had couple of situations with nativescript where the UI wont refresh (the zone will not trigger a UI refresh or something) and the easiest way to do it is to force the code to run into the zone. Here is small example
我有几个使用 nativescript 的情况,其中 UI 不会刷新(区域不会触发 UI 刷新或其他东西),最简单的方法是强制代码运行到区域中。这是小例子
export class TestClass {
constructor(private _ngZone: NgZone) {
}
someOperation(){
this._ngZone.run(() => {
//Do whatever you want here
})
}
}
I know this is not the best solution but thats the cleanest workaround currently I think
我知道这不是最好的解决方案,但这是目前我认为最干净的解决方法
Here is another question that I asked months ago related to this: Angular 2 How to get Angular to detect changes made outside Angular?
这是我几个月前提出的另一个与此相关的问题:Angular 2 How to get Angular to detect changes made out of Angular?
回答by abz
There seems to be a problem with how async operations and change detection is being handled in nativescript-angular when third party plugins are involved.
当涉及第三方插件时,如何在 nativescript-angular 中处理异步操作和更改检测似乎存在问题。
The current suggestion is to wrap all async notify calls within a zoned callback function.
当前的建议是将所有异步通知调用包装在分区回调函数中。
The following video explains the issue and solution. Hope this helps. http://www.nativescriptsnacks.com/videos/2016/06/13/zoned-callbacks.html
以下视频解释了问题和解决方案。希望这可以帮助。 http://www.nativescriptsnacks.com/videos/2016/06/13/zoned-callbacks.html
More details on a corresponding feature request in Nativescript is present here. https://github.com/NativeScript/NativeScript/issues/2229
此处提供了有关 Nativescript 中相应功能请求的更多详细信息。 https://github.com/NativeScript/NativeScript/issues/2229
回答by paulpdaniels
I would guess because the change detection is not being triggered when the next
block in the subscribe is called so the change to this.tabs
is not detected until changed detection triggered by the button press.
我猜是因为在next
调用订阅中的块时不会触发this.tabs
更改检测,因此在按下按钮触发更改检测之前不会检测到更改。
You should be able to simplify your Observable and just do:
您应该能够简化您的 Observable 并执行以下操作:
this.tabs = this._menuService.getMenu()
//Convert the Array into a flattened Observable
.flatMap((menus) => menus ? menus.map(({title}) => {title}) : []);
Which will flatten the array into an Observable implicitly for your ngFor
block.
这将为您的ngFor
块隐式地将数组展平为 Observable 。