ng对于不更新视图,除非单击视图角度



我也尝试了detectChanges((,marforCheck((,重新分配,但没有任何变化。它们只是在我再次单击视图后发生变化。 场景: 我从商店获取数据,我在订阅功能中成功跟踪了数据更改。

this.allInfo$.subscribe(data => {
this.allInfos = data;
});
<div (click)="addInfo(social)" *ngFor="let info of allInfos"
[ngClass]="{'active': info.connected}">
<span>{{info.name}} {{info.connected}}</span>
</div>

当我点击addInfo时,应用程序将打开第三方对话框,如Firebase登录,如果成功将返回新数据并更新到我跟踪的所有Info$。但是观点没有改变吗?那是棱角分明的虫子吗?如果我单击屏幕上的某处,则查看更改 我的角度版本 7

已更新:我的问题已通过使用 _ngZone.run(( 得到解决

您将单击事件保留在 上,因此当您单击该div 时,它正在更新。

<div  *ngFor="let info of allInfos"
[ngClass]="{'active': info.connected}">
<span (click)="addInfo(social)">{{info.name}} {{info.connected}}</span>
</div>

在此代码中,当您单击跨度时,视图将更新

trackBy

<div (click)="addInfo(social)" *ngFor="let info of allInfos;trackBy:trackByFunction"
[ngClass]="{'active': info.connected}">
<span>{{info.name}} {{info.connected}}</span>
</div>

.ts

trackByFunction(index, info){
if(!info)return null;
return info.id; //or return index;
}

链接:-https://medium.com/better 编程/改进角度-ngfor-performance-through-trackby-ae4cf943b878

订阅不会在数据库中放置"侦听器",因此数据库中的任何更改都是反射。数据库中的每个更改,您都需要或再次获取列表或手动添加到数组 allInfos。

您说"当我点击addInfo时,应用程序将打开第三方对话框,例如Firebase登录,如果成功将返回新数据并更新到allInfo$">

我不知道你的addInfo,所以我支持你的addInfo是这样的

addInfo(data)
{
this.service.addData(data).subscribe(res=>{
console.log(res) //generally success
})
}

你可以这样喜欢

addInfo(data)
{
this.service.addData(data).subscribe(res=>{
if (sucess)
this.allInfos.push(data)
})
}

或 添加信息(数据( { this.service.addData(data(.pipe( switchMap(res=>{ return res.success?this.allInfo$:of(null( }) (.subscribe(res=>{ 如果(res( this.allInfos=res }) }

有可能"第三方对话框在你的$allInfo旁边做一个",(比所有这些是不必要的(,但我不知道。想象一下,您有一个典型的 CRUD 服务,例如

@Injectable()
export class ProductService {
endpoint: string = '[YOUR_DB_SERVER_IP]';
constructor(
private http: HttpClient
) {}
// CREATE
createProduct(productToCreate: IProduct): Observable<IProduct[]> {
return this.http.post(`${this.endpoint}/products`, productToCreate);
}
// READ
readProducts(): Observable<IProduct[]> {
return this.http.get(`${this.endpoint}/products`);
}
// UPDATE
updateProduct(objToUpdate: IProduct): Observable<IProduct[]> {
return this.http.patch(`${this.endpoint}/products/${objToUpdate.id}`, objToUpdate};
}
// DELETE 
deleteProduct(): Observable<IProduct[]> {
return this.http.delete(`${this.endpoint}/products/${objToDelete.id}`);
}
}

我们正在改变,所以每个变化都会发出一个事件

private dbsChangeSubject = new Subject<any>();
dbsChange = this.dbsChangeSubject .asObservable();
// CREATE
createProduct(productToCreate: IProduct): Observable<IProduct[]> {
return this.http.post(`${this.endpoint}/products`, productToCreate).pipe(
tap(result=>{
if (result.success)
this.dbsChangeSubject.next(true)
}))
);
}
// UPDATE
updateProduct(objToUpdate: IProduct): Observable<IProduct[]> {
return this.http.patch(`${this.endpoint}/products/${objToUpdate.id}`, objToUpdate.pipe(
tap(result=>{
if (result.success)
this.dbsChangeSubject.next(true)
}))
);;
}
// DELETE 
deleteProduct(): Observable<IProduct[]> {
return this.http.delete(`${this.endpoint}/products/${objToDelete.id}`).pipe(
tap(result=>{
if (result.success)
this.dbsChangeSubject.next(true)
}))
);
}
}

知道我们可以订阅

this.service.dbsChange().pipe(
startWith(true),
switchMap(()=>{
this.service.readProducts()
})).subscribe(res=>{
this.products=res
})

在这里,我们订阅"dbsChange",而不是readProducts((,所以我们正在收听所有this.dbsChangeSubject.next

正如 dlam 在他编辑的问题中所说,在新窗口中使用NgZone可以解决问题。

例:

import { NgZone} from '@angular/core';
export class NewWindowComponent implements OnInit{
constructor(private ngZone: NgZone) { }
ngOnInit() {
this.someService.getChangedData.subscribe(data => {
this.ngZone.run(() => {
this.someData= data;
});
});
}
}

最新更新