LoginSignup
8
6

More than 1 year has passed since last update.

ざっくりFirestore + Vue.jsの使い方

Last updated at Posted at 2019-12-05

この記事はただの集団 Advent Calendar 2019の5日目の記事です。
( 内容が薄くて大変申し訳ありません:bow_tone1: )

ざっくりFirestore + Vue.jsの使い方

フロントエンドでも簡単にサーバーサイド込みで実装できると噂のFirebase
いじってみたので簡単にですがFirebaseのサービスの一つFirestore についてまとめてみました。

● Firestoreについて

FirestoreRealtime Database の進化版のようなものです。
ドキュメント指向のいわゆる NoSQL と言われるタイプのDBで、
MongoDBとかDynamoDBと同じカテゴリに入るやつです。

● 開発環境

  • Mac : Mojave ~ Catalina
  • Node.js : v10.17.0 (nodebrewでバージョン管理)
  • yarn : v1.19.1 (brewでインストール)
  • Vue CLI : v3.12.1 (globalにインストール)
  • Firebase CLI : v7.8.1 (globalにインストール)

■ 初期設定

社内の勉強会で使用した資料ですが、下記を参考に初期設定。

■ Firebaseパッケージをインストール

terminal
# firebaseパッケージをインストール
$ yarn add firebase

# authとか使うときに便利らしいのでとりあえずいれる
$ yarn add firebaseui

■ Firebaseパッケージをインポートする

/src/plugins/firebaseConfig.js
import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/storage";
import "firebase/auth";

// ↓は各自異なる値になると思います
const firebaseConfig = {
  apiKey: "hogehoge",
  authDomain: "hoge.firebaseapp.com",
  databaseURL: "https://hoge.firebaseio.com",
  projectId: "hoge",
  storageBucket: "hoge.appspot.com",
  messagingSenderId: "123456789",
  appId: "hogefuga"
};

export default firebase.initializeApp(firebaseConfig);
/src/plugins/firestore.js
// initializeしたものをimportする
import firebase from "@/plugins/firebaseConfig";
export default firebase.firestore();
/src/plugins/cloudStorage.js
// initializeしたものをimportする
import firebase from "@/plugins/firebaseConfig";
export default firebase.storage();

● Firestoreを試す

あくまでサンプルなので、誰でも全件データが編集削除できるザル仕様になってます。
コード自体も簡略化していますので、そのままだと動かない可能性が・・・

■ Create

src/views/Create.vue
<template>
<div class="create">
  <input v-model="inputData.name" type="text">
  <button @click="create">送信</button>
</div>
</template>
<script>
import Firebase from 'firebase/app'
import db from '@/plugins/firestore'
export default {
  data () {
    return {
      inputData: {
        name: '',
      }
    }
  },
  methods: {
    create () {
      db.collection('records')
        .add({
          name: this.inputData.name,
          createBy: this.$store.state.user.uid,
          createAt: Firebase.firestore.Timestamp.now(),
          updateAt: Firebase.firestore.Timestamp.now()
        })
        .then(docRef => {
          alert(`Document written with ID: ${docRef.id}`);
        })
        .catch(error => {
          alert(`Error adding document: ${error}`);
        });
    }
  }
}
</script>

■ Read

/src/views/Read.vue
<template>
  <div class="read">
    <ul>
      <li v-for="(record, index) in records" :key="index">
        {{ record.data.name }}
      </li>
    </ul>
  </div>
</template>
<script>
import Firebase from 'firebase/app'
import db from '@/plugins/firestore'
export default {
  data () {
    return {
      records:[]
    }
  },
  methods: {
    read () {
      // とりあえず全件取得。
      db.collection('records')
        .get()
        .then(querySnapshot => {
          querySnapshot.forEach(doc => {
            this.records.push({
              id: doc.id,
              data: doc.data()
            })
          })
        })
    }
  },
  created () {
    this.read()
  }
}
</script>

↓取得条件を含めるとこんな感じで書けるらしい。

/src/views/Read.vue
<script>
// 前略
read () {
  db.collection('records')
    .where('createBy', '==', this.$store.state.user.uid)
    .then(querySnapshot => {
      querySnapshot.forEach(doc => {
        this.records.push({
          id: doc.id,
          data: doc.data()
        })
      })
    })
}
// 後略
</script>

■ Update

/src/views/Update.vue
<template>
  <div class="update">
    <input v-model="recordId" type="text">
    <input v-model="editedData.name" type="text">
    <button @click="delete">更新</button>
  </div>
</template>
<script>
import Firebase from "firebase/app";
import db from "@/plugins/firestore";
export default {
  data () {
    return {
      recordId: 'hoge',
      editedData: {
        name: '',
        updateAt: Firebase.firestore.Timestamp.now()

      }
    }
  },
  methods: {
    // 指定されたIDのdataを更新する
    update () {
      db.collection('records')
        .doc(this.recordId)
        .update(this.editedData)
        .then(() => {
          alert('Document successfully updated!')
        })
        .catch(error => {
          console.log('Error updating document: ', error)
        })
    }
  }
}
</script>

■ Delete

/src/views/Delete.vue
<template>
  <div class="delete">
    <input v-model="recordId" type="text">
    <button @click="delete">削除</button>
  </div>
</template>
<script>
import Firebase from 'firebase/app'
import db from '@/plugins/firestore'
export default {
  data () {
    return {
      recordId: 'hoge',
    }
  },
  methods: {
    // 指定されたIDのdataを削除する(物理削除)
    delete () {
      db.collection('records')
        .doc(this.recordId)
        .delete()
        .then(() => {
          alert('Document successfully deleted!');
        })
        .catch(error => {
          console.log('Error removing document: ', error)
        })
    }
  }
}
</script>

おまけ

Cloud Storageも主題として書きたかったのですが、Update,Delete機能が間に合いませんでした。
でも折角なので載せておきます

■ Create

/src/views/CreateStorage.vue
<template>
<div class="createStorage">
  <input type="file" @change="onFileChange">
  <button @click="fileSubmit()">登録</button>
</div>
</template>
<script>
import storage from '@/plugins/cloudStorage'
import db from '@/plugins/firestore'
export default {
  data  () {
    return {
      // uploadするファイルを格納
      file: [],
      // 登録用meta情報
      submitData: {
        filePath: '',
        createBy: this.$store.state.user.uid
      },
    }
  },
  methods: {
    onFileChange() {
      this.submitData.filePath = this.file.name;
    },
    fileInfoRegister(meta_data) {
      db.collection('meta')
        .add(meta_data)
        .then(docRef => {
          console.log(docRef)
        })
        .catch(error => {
          console.log(error)
        });
    },
    fileSubmit() {
      if (this.file.name) {
        // storageのrootディレクトリにファイルを保存する想定
        storage.ref()
          .child(`${this.submitData.filePath}`)
          .put(this.file)
          .then(snapshot => {
            console.log(`Uploaded a file: ${snapshot.metadata.fullPath}`)
          })
          .catch(error => {
            console.error(`${error.code}:${error.message}`)
          })
          this.fileInfoRegister(this.submitData)
          this.submitData = {}
        }
      }
    },
  }
}
</script>

■ Read

/src/views/ReadStorage.vue
<template>
<div class="readStorage">
  <ul>
   <li v-for="(refImgUrl, index) in refImgUrls" :key="index">
      <img :src="refImgUrl">
   </li>
  </ul>
</div>
</template>
<script>
import storage from '@/plugins/cloudStorage'
import db from '@/plugins/firestore'
export default {
  data  () {
    return {
      // dbから取得したもの
      getImgUrls: [],
      // storageからrefで取得したもの
      refImgUrls: [],
    }
  },
  methods: {
    fileRead () {
      db.collection('meta')
        .where('createBy', '==', this.$store.state.user.uid)
        .then(querySnapshot => {
          querySnapshot.forEach(doc => {
            this.getImgUrls.push({
              id: doc.id,
              data: `${doc.data().parentDir}${doc.data().fileName}`
            })
          })
          this.getImgUrls.forEach(ref => {
            storage
              .ref()
              .child(ref.data)
              .getDownloadURL()
              .then(url => {
                this.refImgUrls.push(url)
              })
              .catch(error => {
                console.log(error)
              })
          })
      })
    }
  }
  created() {
    this.fileRead()
  },
}
</script>

あとがき

FirebaseはJSが読み書きできれば、自分のアイディアを形にできるので触っていてとても楽しいです。
デメリットがあるとすれば、各種rulesファイルの書き方が独特だということでしょうかね。
ちなみにサンプルコードはテストモードで動かしてますので、権限周りのルールは本当にザルです。

今回は題材をFirestoreに絞りましたが、
Cloud Storage のリベンジと Firebase Authenticationでの権限設定
Cloud Functions + Firebase Admin SDKで通知設定なども機会があれば記事を書いて見ようかと思います。

8
6
0

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
8
6