angular 4个变量没有第一次更新
angular 4 variable not updating the first time
这是我面临的问题。
我在分配给指令的组件内有一个变量。我正在使用 ngrx 来调度和订阅事件。所以问题是变量没有第一次更新。之后就没有问题了。
我有一个 google 地图和上面的图标,单击任何图标时,它都会使用 id 和地图边界调用服务器,然后使用返回的数据调度操作。
private getFromServer(id, bound_corners){
let params = { bounds: bound_corners }
return this.restangular.all('get-data/'+id)
.customGET("", params)
.map((d:any)=>{
return d.plain();
});
}
public onClick(icon){
let bound_corners = this.getMapBounds();
this.getFromServer(icon.id, bound_corners).subscribe((d)=>{
this.store.dispatch(new action.detail(d, id));
});
}
组件中class
let temp = store.select(fromRoot.getIconDetail);
temp.subscribe((d)=>{
this.data = d;
})
在组件 this.data 中没有第一次更新。如果我控制台日志(this.data)然后它工作但它不会在 html.
中更新
如果我像这样从 getFromServer 订阅中取出调度操作:
public onClick(icon){
let bound_corners = this.getMapBounds();
let temp_data = {name:"test","id":0};
this.store.dispatch(new action.detail(temp_data, id));
}
然后就可以了。
目前我有一种使用 ChangeDetectorRef 的解决方案。
constructor(private chRef: ChangeDetectorRef){
let temp = store.select(fromRoot.getIconDetail);
temp.subscribe((d)=>{
this.data = d;
this.chRef.detectChanges();
});
}
我不确定这是否正确,但我无法弄清楚发生了什么或任何其他解决方案。
任何帮助将不胜感激。谢谢
也许不是将订阅分配给变量,而是直接执行它。
constructor(){
store.select(fromRoot.getIconDetail)
.subscribe(d => {
this.data = d;
})
}
值得注意的是,当您使用.subscribe 时,您需要在组件被销毁时取消订阅,否则您将在重新访问和重新加载组件时最终在 Observable 上累积多个订阅。
为防止这种情况发生并防止内存泄漏,您应该在销毁每个组件时取消订阅 Observable。
将这些导入添加到您的组件中
import 'rxjs/add/operator/takeUntil';
import { Subject } from 'rxjs/Subject';
将此添加到您的 class - 我通常在构造函数上方执行此操作。
private ngUnsubscribe: Subject<any> = new Subject<any>()
添加一个 ngOnDestroy 函数
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
然后将其添加到您的 .subscribe 之前(您应该在每个具有倍数的组件中的 .subscribe 之前使用这个确切的语法)。
.takeUntil(this.ngUnsubscribe)
所以在你的情况下,它看起来像这样。
constructor(){
store.select(fromRoot.getIconDetail)
.takeUntil(this.ngUnsubscribe)
.subscribe(d => {
this.data = d;
})
}
所以发生的事情是订阅将保持活动状态,直到您导航离开该组件,此时 ngOnDestroy 会触发,它会彻底取消对 Observable 的订阅。
这就是我最终做到的。希望有人 post 更好的解决方案。感谢 Stephen 的退订建议。
constructor(private ngZone: NgZone){
store.select(fromRoot.getIconDetail)
.takeUntil(ngUnsubscribe)
.subscribe((d)=>{
this.ngZone.run(() => {
this.someFunction(d);
});
});
}
在具有单向数据流范例的 Angular 中,所有用于存储数据的数据订阅都应直接在 html 异步管道中使用。
您还没有显示您的 html,但假设它类似于 <div>{{data}}</div>
。
相反,它应该是 <div>{{temp | async}}</div>
。
如果您正在引用可观察对象的属性,则需要将异步管道括起来:<div>{{ (temp | async).someProp }}</div>
。
此外,根据商店的初始状态,添加 安全导航 ('?') 运算符通常很有用,以避免在预初始化阶段出错:<div>{{ (temp | async)?.someProp }}</div>
.参考:
这应该使您的模板对商店更改做出反应,而无需调用更改检测(这就是您使用 ChangeDetectorRef 灵魂和 NgZone 灵魂所做的)。查看 ngrx 示例应用程序,例如 find-book-page.ts。请参阅命名约定,为可观察对象添加后缀“$”很有用,因此使用 temp$ 而不是 temp。
顺便说一句,我没有发现显式调用更改检测有什么问题 - 有时在包装第 3 方库时需要这样做。
这是我面临的问题。
我在分配给指令的组件内有一个变量。我正在使用 ngrx 来调度和订阅事件。所以问题是变量没有第一次更新。之后就没有问题了。
我有一个 google 地图和上面的图标,单击任何图标时,它都会使用 id 和地图边界调用服务器,然后使用返回的数据调度操作。
private getFromServer(id, bound_corners){
let params = { bounds: bound_corners }
return this.restangular.all('get-data/'+id)
.customGET("", params)
.map((d:any)=>{
return d.plain();
});
}
public onClick(icon){
let bound_corners = this.getMapBounds();
this.getFromServer(icon.id, bound_corners).subscribe((d)=>{
this.store.dispatch(new action.detail(d, id));
});
}
组件中class
let temp = store.select(fromRoot.getIconDetail);
temp.subscribe((d)=>{
this.data = d;
})
在组件 this.data 中没有第一次更新。如果我控制台日志(this.data)然后它工作但它不会在 html.
中更新如果我像这样从 getFromServer 订阅中取出调度操作:
public onClick(icon){
let bound_corners = this.getMapBounds();
let temp_data = {name:"test","id":0};
this.store.dispatch(new action.detail(temp_data, id));
}
然后就可以了。
目前我有一种使用 ChangeDetectorRef 的解决方案。
constructor(private chRef: ChangeDetectorRef){
let temp = store.select(fromRoot.getIconDetail);
temp.subscribe((d)=>{
this.data = d;
this.chRef.detectChanges();
});
}
我不确定这是否正确,但我无法弄清楚发生了什么或任何其他解决方案。
任何帮助将不胜感激。谢谢
也许不是将订阅分配给变量,而是直接执行它。
constructor(){
store.select(fromRoot.getIconDetail)
.subscribe(d => {
this.data = d;
})
}
值得注意的是,当您使用.subscribe 时,您需要在组件被销毁时取消订阅,否则您将在重新访问和重新加载组件时最终在 Observable 上累积多个订阅。
为防止这种情况发生并防止内存泄漏,您应该在销毁每个组件时取消订阅 Observable。
将这些导入添加到您的组件中
import 'rxjs/add/operator/takeUntil';
import { Subject } from 'rxjs/Subject';
将此添加到您的 class - 我通常在构造函数上方执行此操作。
private ngUnsubscribe: Subject<any> = new Subject<any>()
添加一个 ngOnDestroy 函数
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
然后将其添加到您的 .subscribe 之前(您应该在每个具有倍数的组件中的 .subscribe 之前使用这个确切的语法)。
.takeUntil(this.ngUnsubscribe)
所以在你的情况下,它看起来像这样。
constructor(){
store.select(fromRoot.getIconDetail)
.takeUntil(this.ngUnsubscribe)
.subscribe(d => {
this.data = d;
})
}
所以发生的事情是订阅将保持活动状态,直到您导航离开该组件,此时 ngOnDestroy 会触发,它会彻底取消对 Observable 的订阅。
这就是我最终做到的。希望有人 post 更好的解决方案。感谢 Stephen 的退订建议。
constructor(private ngZone: NgZone){
store.select(fromRoot.getIconDetail)
.takeUntil(ngUnsubscribe)
.subscribe((d)=>{
this.ngZone.run(() => {
this.someFunction(d);
});
});
}
在具有单向数据流范例的 Angular 中,所有用于存储数据的数据订阅都应直接在 html 异步管道中使用。
您还没有显示您的 html,但假设它类似于 <div>{{data}}</div>
。
相反,它应该是 <div>{{temp | async}}</div>
。
如果您正在引用可观察对象的属性,则需要将异步管道括起来:<div>{{ (temp | async).someProp }}</div>
。
此外,根据商店的初始状态,添加 安全导航 ('?') 运算符通常很有用,以避免在预初始化阶段出错:<div>{{ (temp | async)?.someProp }}</div>
.参考:
这应该使您的模板对商店更改做出反应,而无需调用更改检测(这就是您使用 ChangeDetectorRef 灵魂和 NgZone 灵魂所做的)。查看 ngrx 示例应用程序,例如 find-book-page.ts。请参阅命名约定,为可观察对象添加后缀“$”很有用,因此使用 temp$ 而不是 temp。
顺便说一句,我没有发现显式调用更改检测有什么问题 - 有时在包装第 3 方库时需要这样做。