VuexFireでバインドしたデータをcomputedやmethodsで使う


Nuxt.js+Firebaseの勉強を始めたばかりです。

前回: Nuxt.js + Firebase + VuexFireでデータ表示をソートする

やりたいこと

Vuexfireでバインドしたデータをcomputedやmethodsで使いたいです。

Webページにリストボックスを用意しています。リスト項目の内容をFirestoreで管理します。itemsへの設定はcomputedで行います。

環境

  • Firebase 7.3.0
  • Vue CLI 4.0.5
  • Nuxt.js 2.10.2
  • VuexFire 3.2.0

失敗したこと

例えば、Firestoreの構成は次のようにしておいて、

コレクション ドキュメント フィールド
pages (document) title

pages/index.vueの cumputed...mapGetters({ pages: 'getPages' }) としておいたとします。 template の中で下記コードを書けばtitleフィールドのデータが表示されますよね。

<v-flex v-for="(page, i) in pages" :key="i"
        xs12 sm4 mb-2 pa-2>
  <v-card>
    <v-card-text>
      {{page.title}}
    </v-card-text>
  </v-card>
</v-flex>

ネットで調べると同様の記事が多く出てきますので、フロント技術に疎い私でもコピペすれば期待通り動かすことができました。

だから私は最初、computedやmethodsで利用するときも下記のようなコードで利用できるのではないかと考えました。しかしこれは失敗でした。

これではうまくいきません
for (let page in this.pages) {
  console.log(page.title);
}

この例では、pageには 0,1,2.. が入っているので、 this.pages[page].title でデータを取り出します。

これはうまくいきます
for (let page in this.pages) {
  console.log(this.pages[page].title);
}

私が実装したこと

コレクション ドキュメント フィールド
categories (document) A001: カテA
A002: カテB
A003: カテC
pages/index.vue
<template>
  <v-layout justify-center align-start row wrap>
    <v-flex xs12 sm9 mb-2 >
      <v-card>
        <v-card-text>
          <v-select
            v-model="selectedCategories"
            item-text="label"
            item-value="value"
            :items="categoriesList"
            label="カテゴリーを選んでください"
            return-object
          />
        </v-card-text>
      </v-card>
    </v-flex>
  </v-layout>
</template>

<script>
import { mapGetters } from 'vuex';
import { db } from '../plugins/firebase';

export default {
  data () {
    return {
      selectedCategories: { label: 'カテA', value: 'A001' },
    }
  },
  computed: {
    ...mapGetters({ categories: 'getCategories' }),
    categoriesList: function () {
      let arr = [];

      for (let i in this.categories) {
        let doc = this.categories[i];
        let keys = Object.keys(doc);
        for (let j in keys) {
          let key = keys[j];
          arr.push({ label: doc[key] , value: key });
        }
      }

      return arr;
    },
  },
  mounted () {
    this.$store.dispatch('setCategoriesRef', 
                         db.collection('categories'));
  },
}
</script>
store/index.js
import { vuexfireMutations, firestoreAction } from 'vuexfire';

export const state = () => ({
      categories: [],
    });

export const mutations = {
      ...vuexfireMutations
    };

export const getters = {
      getCategories: (state) => {
        return state.categories;
      },
    };

export const actions = {
      setCategoriesRef: firestoreAction(({ bindFirestoreRef }, ref) => {
        bindFirestoreRef('categories', ref);
      }),
    };