LoginSignup
17
13

More than 3 years have passed since last update.

FirebaseのCloud Firestoreと連携して掲示板を作る【nuxt.js】

Last updated at Posted at 2020-09-09

FirebaseとNuxt.jsで掲示板を作りました。削除ボタンが機能しなかったり未完成の部分があります。

この記事は

  • Firebaseを活用してみたい
  • Nuxt.jsでアプリ作ってみたい

という人向けに書いてみました。
「こんな感じでやれば短時間でFirebaseと連携できます」的なものを記事にしました。作っていく際に参考にした記事と躓いた点も書いていきます。中途半端な出来ですが初心者向けに書いてみました!

Firebaseとは何?

Firebaseはリアルタイムでデータ同期ができるモバイルプラットフォームです。Firebaseを使うとサーバを立てたり、管理や保守がいらなくなるのでフロントサイドの作成に集中できます。

NuxtJSとは何?

NuxtJSは、Vueファイルで記述できるフレームワークです。モジュール構造で拡張でき一部分から徐々に採用することが可能で、静的なページから複雑なwebアプリケーションまで、あらゆるものの作成に使用できます。

以下公式から抜粋

本質的に汎用性があり、さまざまなターゲット(サーバー、サーバーレス、または静的)をサポートし、サーバーサイドのレンダリングは切り替えることができます。
強力なモジュールエコシステムにより拡張可能で、REST や GraphQL エンドポイント、お気に入りの CMS や CSS フレームワークなどさまざまなものに簡単に接続できます。
NuxtJS は Vue.js プロジェクトのバックボーンであり、柔軟でありながら自信を持ってプロジェクトを構築するための構造を提供します。

めちゃくちゃ簡易的な掲示板

できたもの

実際に利用できます!コメントしてみてください!
http://keiziban.tk/about/

機能

名前、コメントの投稿がきる

作成手順

任意のフォルダーに移動してVScodeのTerminalより
yarnを使って以下のコマンドでNuxtプロジェクトを作成することができます。

yarn create nuxt-app cloudfireTest

を実行すると、UIフレームワークなどの機能が必要か聞かれるので選択していき、終了したら
yarn run devで起動させます。無事に終了したら以下のアドレスにアクセスして実行されているか見ます。
http://localhost:3000

続いて

yarn add firebase

でインストールて完了です。
今回にUIフレームワークはBootstrapVueを選択したので、こちらでどのようなスタイルになるのかを調べました。

フォルダ構造

以下のフォルダとファイルで構成されています。
Image from Gyazo

pages

pagesディレクトリに.vueファイルを作成するとページのルーティングができます、index.vue/になり、about.vue/aboutでアクセスできます

about.vue
<template>
  <div class="container">
   <div class="jumbotron">
        <div class="container">
          <h1 class="display-3">掲示板</h1>
        </div>

      <div class="links">
        <client-only placeholder="Loading...">
        <Memo />
        </client-only>

      </div>
    </div>
  </div>
</template>

<script>

import Memo from '~/components/Memo.vue'


export default {
  components: {
    Memo
  }
}
</script>

以下の部分でComponents内に作るMemo.vueが呼び出されます。

<client-only placeholder="Loading...">
        <Memo />
        </client-only>

Components

何度も利用可能な.vueで構成されています。今回のFirebaseとの連携はこちらに書いていきます。まずはComponentsMemo.vueを追加。
Image from Gyazo

Memo.vue
<template>
    <div>
         <p>
            <b-form-input v-model="name" placeholder="名前"></b-form-input>
            <b-form-textarea input v-model="age" placeholder="コメント" id="button"></b-form-textarea> 
            <b-button id="button" size="sm" variant="outline-success" v-on:click="post(); removetext()">投稿</b-button>
        </p>
        <ul v-for="(data, index) in allData" :key="data.id" class="menu-list" >

            <li>

                名前:{{data.name}} <br>
                コメント:{{data.age}}<br>
                <b-button size="sm" variant="outline-danger" class="delete" @click="switchDelateAlarm(); getIndex(index)">
                削除
                </b-button>

            </li>
            </ul>
            <div v-show="showDelateAlarm" id="overlay">
                <div id="delateAlarm">
                    <p>コメントを削除します</p>
                        <b-button size="sm" variant="outline-dark" v-on:click="closeModal">
                        戻る
                        </b-button>
                        <b-button  size="sm" variant="outline-danger" @click="switchDelateAlarm(); deleteItem(data.id)">
                        削除
                        </b-button>
                </div>
            </div>
    </div>
</template>

<script>
import firebase from "firebase/app";
import "firebase/firestore";



export default {
    components: {},

    data(){
        return{
            db: {},
            allData: [],
            name: '',
            age: '',
            showDelateAlarm: false,
            id: [],

        }
    },



    methods: {
        init: () => {
            const config = {
                apiKey: "",
                authDomain: "",
                databaseURL: "",
                projectId: "",
                storageBucket: "",
                messagingSenderId: "",
                appId: "",
                measurementId: ""
            };
            firebase.initializeApp(config);
        },

        post: function(){
            const testId = firebase.firestore().collection('memos').doc().id; //ユニークなIDを生成
            const docRef = firebase.firestore().collection('memos').doc(testId);
            const setAda = docRef.set({
                name: this.name,
                age: this.age,
                createdAt: new Date()
            });
            this.get();
        },

        get: function(){
            this.allData = [];
            firebase.firestore().collection('memos').get().then(snapshot => {
                snapshot.forEach(doc => {
                    this.id = doc.id;
                    console.log(this.id); 
                    const array = [];
                    console.log(array);
                    this.allData.push(doc.data());
                })
            });

        },
        getIndex: function() {
            console.log(firebase.firestore().collection('memos'));

        },
        deleteItem: function(deleteId, getIndex) {
            const db = firebase.firestore();
            db.collection("memos").doc(deleteId).delete().then(function() {
            console.log("Document successfully deleted!");

            }).catch(function(error) {
                console.error("Error removing document: ", error);
            });
            this.showDelateAlarm = false;
            this.get();
        },


        switchDelateAlarm: function() {
            this.showDelateAlarm = true
        },
        closeModal: function(){
           this.showDelateAlarm = false
        },
        removetext: function() {
       this.name = '';
       this.age = '';

    },
    },

    mounted(){
        this.init();
        this.get();
    },


}


</script>

<style>
#delateAlarm{
  z-index:2;
  width:50%;
  padding: 1em;
  background:#fff;
}

#overlay{
  /* 要素を重ねた時の順番 */

  z-index:1;

  /* 画面全体を覆う設定 */
  position:fixed;
  top:0;
  left:0;
  width:100%;
  height:100%;
  background-color:rgba(0,0,0,0.5);

  /* 画面の中央に要素を表示させる設定 */
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10%;

}
ul {
    display: block;
    margin-block-start: 1em;
    margin-block-end: 1em;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
    padding: 0px;
    list-style: none;
}
#button {
    margin-top: 2px;
}

</style>


Cloud Firestoreの設定

こちらの部分にファイヤーベースの設定→全般の下のほうにあるマイアプリ
からコピー&ペーストします。
Image from Gyazo

Memo.vue
const config = {
                apiKey: "",
                authDomain: "",
                databaseURL: "",
                projectId: "",
                storageBucket: "",
                messagingSenderId: "",
                appId: "",
                measurementId: ""
            };

今回はあらかじめCloud Firestoreのコレクションにmemos作成しておきます。

Image from Gyazo

設定

以下はpostの部分を抜粋しています。

Memo.vue
post: function(){
            const testId = firebase.firestore().collection('memos').doc().id; //ユニークなIDを生成
            const docRef = firebase.firestore().collection('memos').doc(testId);
            const setAda = docRef.set({
                name: this.name,
                age: this.age,
                createdAt: new Date()
            });
            this.get();
        },

Image from Gyazo

躓いた部分

削除ボタンの実装に躓きました。ボタンに紐づいたドキュメントidが取得できずボタンは配置されていますが、機能しません。

参考にした記事

終わりに

読んでいただきありがとうございました、よくわからん部分もあったと思います。私自身わかっていない部分が多いですが、とにかく一言いってやりたいという方!是非こちらで絡んでやってください。

17
13
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
13