kama0244
@kama0244 (カマ ちゃん)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【初心者です】Firebaseの保存データを、Vue.jsのdata()に渡したい

解決したいこと

Vue.jsで点数計算アプリを制作中です。
現在はFirebaseを使って、点数を保存出来る機能を実装中です。

FirebaseのRialtime Databaseに点数を保存することは出来ました。
Firebaseのコンソールで、意図通りに点数が保存されていることを確認出来ました。
しかし、その保存された点数を表示させることが出来ずに悩んでいます。

発生している問題・エラー

具体的にはWebページをリロードすると、input要素に入力した点数が消えてしまう状態です。

該当するソースコード

<table class="table table-bordered table-striped mt-3">
    <thead class="thead-light">
        <tr>
            <th class="col-sm gameCount"><span></span>{{ gameCount }}<span> 試合</span></th>
            <th class="col-lg">ゲート1</th>
            <th class="col-lg">ゲート2</th>
            <th class="col-lg">ゲート3</th>
            <th class="col-lg">ゲート4</th>
            <th class="col-lg">ゴール</th>
            <th class="col-md">総打数</th>
            <th class="col-md">加算点</th>
            <th class="col-md">Total</th>
        </tr>
    </thead>
    <tbody>
        <tr
            v-for="(row, number) in rows"
            :key="number"
        >
            <th class="col-sm">{{ row.number }}<br>{{ row.name }}<br>さん</th>
            <td>
                <counter-hit v-model="row.scores.gate1.hit" :database="row.number + '-' + 'gate1-hit'"></counter-hit>
                <hoop-in v-model="row.scores.gate1.in"></hoop-in>
            </td>
            <td>
                <counter-hit v-model="row.scores.gate2.hit" :database="row.number + '-' + 'gate2-hit'"></counter-hit>
                <hoop-in v-model="row.scores.gate2.in"></hoop-in>
            </td>
            <td>
                <counter-hit v-model="row.scores.gate3.hit" :database="row.number + '-' + 'gate3-hit'"></counter-hit>
                <hoop-in v-model="row.scores.gate3.in"></hoop-in>
            </td>
            <td>
                <counter-hit v-model="row.scores.gate4.hit" :database="row.number + '-' + 'gate4-hit'"></counter-hit>
                <hoop-in v-model="row.scores.gate4.in"></hoop-in>
            </td>
            <td>
                <counter-hit v-model="row.scores.goal.hit" :database="row.number + '-' + 'goal-hit'"></counter-hit>
                <hoop-in v-model="row.scores.goal.in">ネットイン</hoop-in>
            </td>
            <td>
                <div class="sum">{{ sum(number) }}</div>
            </td>
            <td>
                <div class="addition">{{ addition(number) }}</div>
            </td>
            <td>
                <div class="total">{{ sum(number) + addition(number) }}</div>
            </td>
        </tr>
    </tbody>
</table>

例)

/* -------------------------------------------------------------------------
    「打数」のテンプレート
------------------------------------------------------------------------- */
const counterHit = {
    props: ['value', 'database'],
    methods: {
        countUp() {
            this.$emit('input', this.value + 1);
            // プロパティ「database」から行番号を取得
            const number = this.database.slice(0, 1);
            // プロパティ「database」からゲート番号を取得
            const gate = this.database.slice(2);
            // Firebaseにデータを保存
            firebase
                .database()
                .ref(`users/${currentUID}/${number}/${gate}`)
                .set(this.value + 1);
        },
        countDown() {
            if ( this.value > 0 ) {
                this.$emit('input', this.value - 1);
                const number = this.database.slice(0, 1);
                const gate = this.database.slice(2);
                firebase
                    .database()
                    .ref(`users/${currentUID}/${number}/${gate}`)
                    .set(this.value - 1);
            }
        },
    },
    template: `
        <form>
            打数
            <div class="form-group input-group">
                <div class="input-group-prepend">
                    <button
                        type="button"
                        @click="countUp"
                        class="btn btn-primary btn-up"
                    >+</button>
                </div>
                <input
                    type="number"
                    :value="value"
                    min="0"
                    disabled
                    class="form-control hit-input"
                >
                <div class="input-group-append">
                    <button
                        type="button"
                        @click="countDown"
                        class="btn btn-secondary btn-down"
                    >-</button>
                </div>
            </div>
        </form>
    `,
};


/* -------------------------------------------------------------------------
    Vueインスタンスの内容
------------------------------------------------------------------------- */
new Vue({
    el: '#app',
    data() {
        return {
            gameCount: 1, // 試合数のデータ
            rows: [], // 各ゲートの打数とフープインの配列データ
        };
    },
    // 各ゲートに配列rowsのデータを登録
    created() {
        for (const number of 'ABCDEF') {
            this.rows.push({
                number: number,
                name: '',
                scores: {
                    gate1: {hit: 0, in: ''},
                    gate2: {hit: 0, in: ''},
                    gate3: {hit: 0, in: ''},
                    gate4: {hit: 0, in: ''},
                    goal: {hit: 0, in: ''},
                },
            });
        }
    },
Firebaseの保存データ

アプリ名
  ↳users
    ↳ユーザID(user.uid)
      ↳A
        ↳gate1-hit: 0
        ↳gate2-hit: 0
        ↳gate3-hit: 0
        ↳gate4-hit: 0
        ↳goal-hit: 0
      ↳B
        ↳gate1-hit: 0
        ↳gate2-hit: 0
        ↳・・・・・・・・・・・・・・・・・・・・・・・・・・・・

自分で試したこと

Vueインスタンスのcreated()でscoresを初期化しているので、ページをリロードすると入力した点数が0に戻るのだと思います。
ここを0で初期化せずに、Firebaseに保存されたデータを渡すことが出来れば解決できるのではと考えています。

created()の中に、firebase.database().ref(キー名).on()を書いてみたりしましたが、上手くいきませんでした。
そもそもcreated()やdata()に着目している、私の考えが間違っているのでしょうか?

0

1Answer

getValue()という関数を下記のように作成。

const getValue = () => {
if (currentUID !== null) {
firebase
.database()
.ref(users/${currentUID})
.on('value', (snapshot) => {
const gates = [
'gate1',
'gate2',
'gate3',
'gate4',
'goal',
];
let i = 0;
for (const number of 'ABCDEF') {
const appData = app._data.rows[i]['scores'];
for (const gate of gates) {
// Firebaseから打数データを取得
const gateHit = snapshot.val()[number][${gate}-hit];
const gateIn = snapshot.val()[number][${gate}-in];
// 取得したデータを(app)Vueのdata()に渡して表示
appData[gate]['hit'] = gateHit;
appData[gate]['in'] = gateIn;
}
i++;
}
});
};
};

ログイン状態が変化した時のコールバックにgetValue();を登録したら、意図通りに実装出来ました。

// ユーザのログイン状態が変化したら呼び出される、コールバック関数を登録
// ログインユーザのUID
let currentUID = null;

firebase.auth().onAuthStateChanged((user) => {
if (user) {
console.log('状態:ログイン中');
currentUID = user.uid;
changeView();
getUserName();
getValue();
} else {
console.log('状態:ログアウト');
currentUID = null;
changeView();
}
});

ありがとうございました。

0Like

Your answer might help someone💌