FIrebaseとVue.jsを利用した簡易掲示板アプリのサンプル

Firebaseを試してみたいと思いたち、Vue.jsを使って簡易的な掲示板アプリを作ってみました。

サンプルのため機能は限定的ですが、ソーシャルゲームのマルチ募集掲示板ぐらいには使えるかもしれません。

こんな感じです。
scr

デモサイト
ソースコード

実装について

構成要素

  • Firebase Firestore
  • Firebase Functions
  • Vue
  • Vue-Router

ソースコード抜粋

Firebaseを初期化する部分

src/App.vue

import firebase from 'firebase';
import config from '@/config/dev.config';

firebase.initializeApp(config.firebase);

スレッドを作成する部分

Firebase FunctionをHTTP経由で呼び出すだけです。

Components/Main.vue

export default({
    methods {
    createThreadExec() {
      this.loading = true;
      axios.post(config.endpoints.createThread, this.newThread)
      .then(() => {
        this.newThreadInput = false;
        this.newThread.name = '';
        this.newThread.comment = '';
        this.refresh();
      }).catch((e) => {
        this.displayError(e);
      });
    },
  },
});

スレッドの一覧を取得する部分

最近更新があったスレッド100件を取得するようにしています。

src/Components/Main.vue

export default({
    methods {
    refresh() {
      const db = firebase.firestore();
      db.collection("threads")
      .orderBy("updateTime", "desc")
      .limit(100).get().then((querySnapshots) => {
        this.threads = [];
        querySnapshots.forEach((doc) => {
          this.threads.push(doc.data());
        });
        this.loading = false;
      }).catch((e) => {
        this.displayError(e);
      });
    },
  }
});

コメントの一覧を取得し、subscribeを開始する部分

最新1000件のコメントを取得し、その後、コメントに更新があったときに通知されるようsubscribeを登録します。
Firestoreの便利なところは、全てのキーに対して自動的にインデックスが作成されるところですね。

Components/Comments.vue

export default({
    methods {
    refresh() {
      const db = firebase.firestore();
            db.collection("comments").doc(this.threadId).collection("comments")
      .orderBy("updateTime", "desc").limit(1000)
      .get().then((querySnapshot) => {
        let commentNumber = this.thread.count;
        this.comments = [];
        querySnapshot.forEach((doc) => {
          this.comments.push(doc.data());
        });
      }).catch((e) => {
        this.displayError(e);
      });
      this.unsubscribe();
      this.unsubscribe = db.collection("comments").doc(this.threadId).collection("comments")
      .onSnapshot((snapshot) => {
        snapshot.docChanges.forEach((change) => {
          if (change.type === "added") {
            this.comments.unshift(change.doc.data());
          }
        });
      });
    },
  }
});

コメントを投稿する部分

スレッド作成同様、Firebase FunctionをHTTP経由で呼び出すだけです。

Components/Comments.vue

export default({
    methods {
    writeComment() {
      this.newComment.threadId = this.threadId;
      axios.post(config.endpoints.addComment, this.newComment)
      .then(() => {
        this.newComment.comment = '';
      })
      .catch((e) => {
        this.displayError(e);
      })
    },
  },
});

Cloud Functions

Functionは2つです。

  • AddComment
    コメントを投稿するFunctionですコメント投稿時に、スレッドのコメント件数をインクリメントするようにしています。
    また、スレッドのupdateTimeを更新することにより、最新のコメントがあったスレッドが上位に表示されるようにしています。
  • CreateThread
    スレッドを作成するFunctionです。

functions/index.js

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const cors = require('cors')({origin: true});

admin.initializeApp(functions.config().firebase);

exports.AddComment = functions.https.onRequest((req, res) => {
    cors(req, res, () => {
        const threadId = req.body.threadId;
        const comment = req.body.comment;
        const username = req.body.username;
        const dateTime = Date.now();
        admin.firestore().collection('comments').doc(threadId).collection('comments')
        .add({
            comment: comment,
            username: username,
            updateTime: dateTime,
        }).catch((e) => {
            console.error(e)
        });
        const threadRef = admin.firestore().collection('threads').doc(threadId);
        threadRef.get().then((t) => {
            return threadRef.update({
                updateTime: dateTime,
                count: t.data().count + 1,
            }).catch((e) => {
                console.error(e)
            });
        }).catch((e) => {
            console.error(e)
        });
        res.send({result: 'Success!'});
    });
  });

exports.CreateThread = functions.https.onRequest((req, res) => {
    cors(req, res, () => {
        const name = req.body.name;
        const comment = req.body.comment;
        const username = req.body.username;
        admin.firestore().collection('threads')
        .add({
            name: name,
            comment: comment,
            username: username,
            updateTime: Date.now(),
                        count: 0,
        }).catch((e) => {
            console.error(e)
        });
        res.send({result: 'Success!'});
    });
  });

Please follow and like us:

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です