具有嵌套 Observable/FirebaseObjectObservable 的 Angular2 ngFor 在更新时闪烁一些数据
Posted
技术标签:
【中文标题】具有嵌套 Observable/FirebaseObjectObservable 的 Angular2 ngFor 在更新时闪烁一些数据【英文标题】:Angular2 ngFor with nested Observable/FirebaseObjectObservable flashes some data on update 【发布时间】:2017-02-22 23:56:55 【问题描述】:我正在尝试使用 AngularFire2 创建一个简单的聊天应用程序。用户登录 facebook 并将他们的个人资料信息保存到 users/uid。然后,每次用户发送聊天时,它都会将他们的 UID 与消息一起发送。我正在尝试将 UID 映射到当前正在工作的用户信息。但是,当我添加/删除消息时,一些数据会闪烁,并且似乎正在重新呈现,而不仅仅是使用新信息进行更新。更具体地说,不是我自己刷新的任何个人资料信息。我什至不确定为什么我的不闪烁,因为它都是以同样的方式来自 Firebase。有人知道如何修复闪烁吗?
chat.service.ts
import Injectable from '@angular/core';
import AngularFire, FirebaseListObservable from 'angularfire2';
import Observable from 'rxjs';
import 'rxjs/Rx';
@Injectable()
export class ChatService
chat_list$: Observable<any>;
items$: FirebaseListObservable<any>;
constructor(public af: AngularFire)
this.items$ = af.database.list('/items',
query: limitToLast: 15, orderByKey: true
);
this.chat_list$ = this.items$.map(chats =>
console.log('chats: ', chats);
return chats.map(chat =>
if ( chat.sender !== af.database.object(`users/$chat.uid`) )
chat.sender = af.database.object(`users/$chat.uid`);
return chat;
);
);
home.component.ts
import Component from '@angular/core';
import AuthService from '../services/auth.service';
import ChatService from '../services/chat.service';
@Component(
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
)
export class HomeComponent
name: string;
message: string;
constructor(public auth: AuthService, public chat: ChatService)
auth.isLoggingIn = false;
onMessageSend(form)
console.log('form submit: ', form);
this.chat.items$.push(form);
this.message = '';
removeChat(chat_key)
this.chat.items$.remove(chat_key);
home.component.html
<div class="container m-t-1">
<div class="row">
<div class="col-xs-12">
<h1>Quick Chat App</h1>
<button class="btn btn-danger pull-right" (click)="auth.signout()">Sign Out</button>
</div>
</div>
<form (ngSubmit)="onMessageSend(sendForm.value)" #sendForm="ngForm">
<ul class="m-t-1">
<li *ngFor="let chat of chat.chat_list$ | async">
<img src=" (chat.sender | async)?.photo " >
<span class="message"> chat.message </span> <span class="tag tag-primary m-l-1"> (chat.sender | async)?.name </span>
<span class="tag tag-danger" (click)="removeChat(chat.$key)">X</span>
</li>
</ul>
<div class="input-group m-t-1">
<input name="message" [(ngModel)]="message" type="text" class="form-control" placeholder="Enter message..." autocomplete="off" required>
<span class="input-group-btn">
<button class="btn btn-primary" type="submit"><i class="fa fa-send-o"></i></button>
</span>
</div>
<label for="message" class="pull-right posting-as">Posting as auth.user.name</label>
<input type="hidden" name="uid" [(ngModel)]="auth.user.uid">
</form>
</div>
【问题讨论】:
【参考方案1】:我在简化第一个答案方面的第二次尝试甚至更好。看看吧,我还是看看能不能优化一下。
chat.service.ts
import Injectable from '@angular/core';
import AngularFire, FirebaseListObservable, FirebaseObjectObservable from 'angularfire2';
import Observable from 'rxjs';
import 'rxjs/Rx';
@Injectable()
export class ChatService
chat_list: Array<any>;
chat_list$: Observable<any>;
chat_senders$: any = ;
items$: FirebaseListObservable<any>;
constructor(public af: AngularFire)
this.items$ = af.database.list('/items',
query: limitToLast: 15, orderByKey: true
);
this.chat_list$ = this.items$.map(chats =>
chats.map(chat =>
this.chat_senders$[chat.uid] = af.database.object(`users/$chat.uid`);
this.chat_senders$[chat.uid].subscribe((sender) =>
chat.sender = sender;
);
return chat;
);
return chats;
);
home.component.html
<div class="container m-t-1">
<div class="row">
<div class="col-xs-12">
<h1>Quick Chat App</h1>
<button class="btn btn-danger pull-right" (click)="auth.signout()">Sign Out</button>
</div>
</div>
<form (ngSubmit)="onMessageSend(sendForm.value)" #sendForm="ngForm">
<ul class="m-t-1">
<li *ngFor="let chat of chat.chat_list$ | async">
<img src=" chat.sender?.photo " >
<span class="message"> chat.message </span> <span class="tag tag-primary m-l-1"> chat.sender?.name </span>
<span class="tag tag-danger" (click)="removeChat(chat.$key)">X</span>
</li>
</ul>
<div class="input-group m-t-1">
<input name="message" [(ngModel)]="message" type="text" class="form-control" placeholder="Enter message..." autocomplete="off" required>
<span class="input-group-btn">
<button class="btn btn-primary" type="submit"><i class="fa fa-send-o"></i></button>
</span>
</div>
<label for="message" class="pull-right posting-as">Posting as auth.user.name</label>
<input type="hidden" name="uid" [(ngModel)]="auth.user.uid">
</form>
</div>
【讨论】:
【参考方案2】:这是我第一次尝试在 Firebase 和我的内容之间添加一个额外层的解决方案。其他人有更好的解决方案吗?
chat.service.ts
import Injectable from '@angular/core';
import AngularFire, FirebaseListObservable, FirebaseObjectObservable from 'angularfire2';
import Observable from 'rxjs';
import 'rxjs/Rx';
@Injectable()
export class ChatService
chat_list: Array<any>;
chat_list$: Observable<any>;
chat_senders$: any = ;
items$: FirebaseListObservable<any>;
constructor(public af: AngularFire)
this.items$ = af.database.list('/items',
query: limitToLast: 15, orderByKey: true
);
this.chat_list$ = this.items$.map(chats =>
chats.forEach(chat =>
this.chat_senders$[chat.uid] = af.database.object(`users/$chat.uid`);
);
return chats;
);
this.chat_list$.subscribe(chat_list =>
this.chat_list = chat_list.map(chat =>
this.chat_senders$[chat.uid].subscribe((sender) =>
chat.sender = sender;
);
return chat;
);
console.log(this.chat_list);
);
home.component.html
<div class="container m-t-1">
<div class="row">
<div class="col-xs-12">
<h1>Quick Chat App</h1>
<button class="btn btn-danger pull-right" (click)="auth.signout()">Sign Out</button>
</div>
</div>
<form (ngSubmit)="onMessageSend(sendForm.value)" #sendForm="ngForm">
<ul class="m-t-1">
<li *ngFor="let chat of chat.chat_list">
<img src=" (chat.sender)?.photo " >
<span class="message"> chat.message </span> <span class="tag tag-primary m-l-1"> (chat.sender)?.name </span>
<span class="tag tag-danger" (click)="removeChat(chat.$key)">X</span>
</li>
</ul>
<div class="input-group m-t-1">
<input name="message" [(ngModel)]="message" type="text" class="form-control" placeholder="Enter message..." autocomplete="off" required>
<span class="input-group-btn">
<button class="btn btn-primary" type="submit"><i class="fa fa-send-o"></i></button>
</span>
</div>
<label for="message" class="pull-right posting-as">Posting as auth.user.name</label>
<input type="hidden" name="uid" [(ngModel)]="auth.user.uid">
</form>
</div>
【讨论】:
以上是关于具有嵌套 Observable/FirebaseObjectObservable 的 Angular2 ngFor 在更新时闪烁一些数据的主要内容,如果未能解决你的问题,请参考以下文章