firestore+nuxtでチャットを作る(読み込み回数少ないver)


やりたいこと

  • 以前下記の記事でチャット機能についてまとめたがこのやり方だと、messageごとにuserを読み込むので凄まじく読み込み回数が多くなる(ただし、user情報が変更されたらmessageのiconも変更される。)
  • user_iconの変更を許容してmessageにuser_iconを入れてmessageの読み込みだけですむようにして読み込み回数を減らしたい(firebaseを節約したい)

全体図

  • login時にuser情報をfirestoreとstoreに保存
  • storeのphotoURLをmessage送信時にfirestoreに送る
  • messageからphotoURLを取得

実装!!!

firestoreとstoreに保存

default.vue
  created() {
    firebase.auth().onAuthStateChanged(user => {
      var user = firebase.auth().currentUser
      var name, photoUrl, uid
      if (user != null) {
        uid = user.uid
        name = user.displayName
        photoUrl = user.photoURL
        var db = firebase.firestore()
        db.collection('user').doc(uid).set({
          name: name,
          photoUrl: photoUrl,
          uid: uid,
          created: firebase.firestore.FieldValue.serverTimestamp()
        })
        .then(function (docRef) {
          console.log("")
        })
        .catch(function (error) {
          console.log("")
        })
      }
      if (user) {
        user.isLogin = true
        this.$store.commit('login', user)
      } else {
        this.$store.commit('logout', user)
      }
    })
  },
  methods: {
    googleLogout: function () {
      firebase.auth().signOut().then(() => {
        window.location.href = '/'
      })
    },
    googleLogin: function () {
      firebase.auth().signInWithRedirect(new firebase.auth.TwitterAuthProvider())
    }
  }
}
store/index.js
mutations: {
      login (state, user) {
        state.uid = user.uid
        state.name = user.displayName
        state.isLogin = user.isLogin
        state.photoURL = user.photoURL
      },
      logout (state) {
        state.user = null
      }
    }

message送信

methods: {
    send_message: function () {
      var db = firebase.firestore()
      db.collection('room').doc(this.room_id).collection('message').doc().set({
        user_id: this.$store.state.uid,
        user_photoUrl: this.$store.state.photoURL,
        message_content: this.message_content
      })
      .then(function (docRef) {
        console.log("")
      })
      .catch(function (error) {
        console.log("")
      })
    }

messageの中にphotoURLをいれちゃう

messageの表示

db.collection('room').doc(this.room_id).collection('message').onSnapshot(querySnapshot => {
      querySnapshot.docChanges().forEach(doc => {
        this.messages.push({
          ...doc.doc.data(),
          id: doc.doc.id
        })
      })
    })
  • ...doc.doc.data()でスプレッド構文使ってdocの中を展開している
  • これをmessagesで展開していってmessage.contentでテキストを表示
  • foreachでmessagesにpushで配列を追加していってる