【问题标题】:Angular2 ngFor with nested Observable/FirebaseObjectObservable flashes some data on update具有嵌套 Observable/FirebaseObjectObservable 的 Angular2 ngFor 在更新时闪烁一些数据
【发布时间】: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 }}" alt="{{ (chat.sender | async)?.name }}'s profile picture">
    <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>

【问题讨论】:

    标签: angular firebase firebase-realtime-database angularfire2


    【解决方案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 }}" alt="{{ chat.sender?.name }}'s profile picture">
        <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 }}" alt="{{ (chat.sender)?.name }}'s profile picture">
          <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>
      

      【讨论】:

        猜你喜欢
        • 2016-11-30
        • 2016-05-16
        • 2017-10-31
        • 2019-03-28
        • 1970-01-01
        • 2020-02-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多