PROGBLOG Developers Blog

空想家 Developers Blog

稼ぐ力? とにかくスキルが欲しい。

length が undefined になった時に別の手段で対処する

undefined になる

let list = {
    hoge: 000,
    fuga: 001,
    piyo: 002
};
console.log(list.length) // undefined

undefined になる理由は

オブジェクトに length は効かないとのこと。

オブジェクトについては下記、参照。

JavaScriptでは、数値も文字列も配列も、すべてはオブジェクトである(everything is an object)といわれます。オブジェクトとは、データと属性が一緒になったものを指します。

正直よくわからないので、lengthundefined になった時は都度、別の方法(下記)をを試してみる。

解決方法は

let list = {
    hoge: 000,
    fuga: 001,
    piyo: 002
};
console.log(list.length) // undefined
console.log(Object.keys(list).length) // 3

Object.keys(list).length)

で、無事解決。

Nuxt.js に axios をインストールする

axiosとは

axiosとはブラウザやnode.js上で動くPromiseベースのHTTPクライアントです。 jQueryで言うところのjQuery.ajaxであり、非同期にHTTP通信を行いたいときに容易に実装できます。 Vue.jsでは非同期通信を行うのにaxiosを使うのがスタンダードとなっております。

とのこと。

正直いまいちよくわからないが、主にJSON の取得で用いられる。

ちなみに読み方は アクシオ とのこと。

Nuxt.js にインストールする

npm install --save @nuxtjs/axios

インストールするコマンド。

--savepackage.json に追加するための記述。

@nuxtjs/axios を有効にする。

インストールしただけでは有効化されないので nuxt.config.js に下記のように追記する。

  modules: [
    "@nuxtjs/axios",
  ],

で、完了。

ちなみに使用するページでは下記のようにaxios を読み込む必要がある。

import axios from 'axios'

これでOK。

Firebase の push() で 自動でIDが付与される

はじめに

FirebaseRealtime Database で ログインしたユーザーが投稿できる仕組みを作成している。

ログイン、push() を用いユーザー投稿まではできた。

が、その際に生成されるJSON で思い通りにいかない点があった。

意図しない文字列が

ユーザー投稿テストをし、生成されたJSON を確認したところ、意図しない文字列階層ができている。

▽理想の配列

saite-name-rtdb
    ├ user-id
        ├ today
            ├ 0: "HELLO"
            └ 1: "GOODBYE"
        └ today
            ├ 0: "HELLO"
            └ 1: "GOODBYE"

▽実際の配列

saite-name-rtdb
    ├ user-id
        ├ -謎の文字列
            ├ today
                ├ 0: "HELLO"
                └ 1: "GOODBYE"
        ├ -謎の文字列
            ├ today
                ├ 0: "HELLO"
                └ 1: "GOODBYE"

コードに文字列を生成されるなんて記載はないので、原因はそれ以外だと思われる。

色々、模索しているとドキュメントに下記の記述あった。

マルチユーザー アプリケーションでリストにデータを追加するには push() メソッドを使用します。指定した Firebase 参照に新しい子が追加されるたびに、push() メソッドは一意のキーを生成します。この自動生成されたキーをリスト内の新しい各要素に使用することで、書き込みの競合を伴わずに複数のクライアントが同時に子を同じ場所に追加できます。push() によって生成される一意のキーはタイムスタンプに基づいているため、リストのアイテムは自動的に時系列で並べ替えられます。

つまりこれはFirebase 側の都合で生成された文字列であるとのこと。 いくらコードをいじっても解決できないので、注意が必要。

なお、この文字列を飛ばして子要素を取得する方法は別記事にて記載予定

Nuxt.js で todos.length = 0 が リアクティブに反応しない

はじめに

Nuxt.js でウェブアプリを作成している。

複数のリストを FirebaseRealtime Database に保存するというもの。

v-for を用い、リアクティブに配列に要素を追加し、最後にまるっとデーターベースに保存する。

問題発生

データーベースに保存するためにsibmit をすると、当然データベースに保存はされているが、配列にはデータが残ったままなので、保存後もリストが表示され続ける。

そこで、submit をクリックした瞬間にel.length = 0; で配列のデータを空にする処理をした。

再度、実行。

が、依然、リストは表示され続ける。

念のためコンソールで確認すると配列は空になっている。

つまり、Nuxt.js 側で配列の削除をリアクティブに反応できていないことが分かった。

el.length = 0; は Nuxt.js で感知できない

結論から言うとただそれだけ。

つまり配列を空にする処理を別の書き方にすればOK。

todos.splice(0) で同一処理をすることでリアクティブに反応してくれるようになった。

Nuxt.js とFirebase のRealtime Database に複数要素を保存する

はじめに

過去記事でNuxt.jsFirebaseRealtime Database にデータを保存する処理を記載した。

>Nuxt.js でFirebase にデータを保存する

ただ複数要素を保存する方法がわからなかった。

厳密にいえば、変動するデータ数の保存の仕方が不明だったので、解決してみた。

解決方法

TODOリストのようなものを作成し、配列とし格納したうえで保存をする。

コード

// template(抜粋)

<div class="form">
  <input type="text" v-model="newDo">
  <button @click="add(newDo)">追加</button>
</div>
<div class="todo_list" v-for="(todo, index) in todos" :key="index">
  {{ todo }}
</div>
<button @click="saveContent(todos)">保存</button>

// script(抜粋)

<script>
import firebase from "~/plugins/firebase.js";
export default {
  data() {
    return {
      newDo: '今日やったことは?',
      todos: [],
    };
  },
  methods: {
    add: function(newDo) {
      const todoItem = this.newDo;
      this.todos.push(todoItem);
      this.newDo = "";
    },
    saveContent: function(todos) {
    firebase
      .database()
      // .ref(this.user.uid)
      .ref()
      .push({todos});
  }
  }
}
</script>

追加ボタンを押した時に、input に入力したデータを.pushtodoItem の配列に格納する。

格納された配列をv-for="(todo, index) in todos" で表示する。

最後にその配列を保存する。

配列を使うことで解決した。

Nuxt.js でFirebase にデータを保存する

前提

Firebase 側の設定を完了しておくこと。

>Firebase 側の設定について

Nuxt.js 側の設定

コード

  <div class="form">
    <input type="text" v-model="hoge">
    <button @click="saveContent(hoge)">保存</button>
  </div>
<script>

import firebase from "~/plugins/firebase.js";
// △ https://blog-progblog-web.hatenablog.com/entry/2021/01/10/173554 の記事を参照

export default {
  data() {
    return {
      hoge: 'hello'
    };
  },
  methods: {
    logout: ()=> {
      firebase.auth().signOut();
    },
    saveContent: function(value) {
      var newNoteKey = firebase.database().ref().child('dids').push().key;
      firebase
        .database()
        .ref('dids/' + this.user.uid + '/' + newNoteKey)
        .push({content:value});
    }
  }
}
</script>

解説

フロント(HTML)

<div class="form">
  <input type="text" v-model="hoge">
  <button @click="saveContent(hoge)">保存</button>
</div>

input タグで投稿の仕組みを作成する。

v-model="" を使用しユーザーが入力する値をディレクティブに管理する。

最後に、クリック時にイベントを発火する。saveContent(hoge)hoge は上記と同一になる。

仕組み(JavaScript

最初にhoge: 'hello'hoge の初期値を指定する。

次に肝心のクリック時の仕組みを作成する。

saveContent: function(value) {

value はユーザーが入力したデータなので、hoge と同一。

var newNoteKey = firebase.database().ref().child('dids').push().key;
(中略……)
 .ref('dids/' + this.user.uid + '/' + newNoteKey)

上記は不要? 以下に変更する。

// var newNoteKey = firebase.database().ref().child('dids').push().key;

とりあえず理解できないので、コメントアウト

firebase
  .database()
  .ref('dids/' + this.user.uid)
  .push({value});
}

firebase.database() でデータを取り出す。

ref() でdatabaseのURL指定を指定する?

つまり今回は、dids > ユーザーID となる。

.push({value}); で入力されたデータを保存する。

複数データを保存する

先にTODOリストを構築してまるっと保存する方が良さそうなので、別記事にて記載する。

コード

  <div class="form">
    <input type="text" v-model="hoge">
    <input type="text" v-model="fugo">
    <button @click="saveContent(hoge,fugo)">保存</button>
  </div>

<script>
import firebase from "~/plugins/firebase.js";
export default {
  data() {
    return {
      hoge: 'hello',
      fugo: 'goodbye'
    };
  },
  methods: {
    logout: ()=> {
      firebase.auth().signOut();
    },
    saveContent: function(hoge, fugo) {
    firebase
      .database()
      .ref('dids/' + this.user.uid)
      .push({hoge, fugo});
  }
  }
}
</script>

<style>
</style>

で、いいのか。

現状これで、ふたつのアイテムを登録できたが、汎用性が悪いので、要検討。

先にTODOリストを構築してまるっと保存する方が良さそうなので、別記事にて記載する。

Firebase の Realtime DB を設定する

データベース設定の手順

  1. サイドバーの Realtime Database を選択する。
  2. データベースを作成する を選択する。
  3. Realtime Database のロケーション はデフォルト 米国 のまま。
  4. セキュリティルールは ロックモード を選択する。
  5. Realtime Database > ルールを指定する。
// exeample
{
  "rules": {
    ".read": "true",
    ".write": "true"
  }
}

.read は読み込み、.write は書き込みについての指定。