PROGBLOG Developers Blog

空想家 Developers Blog

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

github にあげたくない場合は「.gitignore 」を活用する

はじめに

NuxtFirebase で練習アプリを作ったので、Github にあげることにした。

しかし Github にあげたくない情報(FirebaseAPI情報 etc)もあったので、それを除く方法を調べてみた。

.gitignore を使用する

調べてみると簡単で、.gitignore というファイルを作り、フォルダにアップする。

そのファイルに除外するファイルを記述する。

ファイルの中身(基本)

# コメントを書く
ファイル名

ファイルの中身(実例)

# Firebase の連携情報
firebase.js

テキストから距離を取ったボーダーを疑似要素以外で表現する

はじめに

今までテキストの下にボーダーを引く際、疑似要素を使用していたがもっと楽な方法を教えてもらった。

比較てみた

See the Pen rNWNLEO by PROGBLOG (@progblog-sank) on CodePen.


従来のやり方

//  HTML

<p class="past_way"><span>HELLO WORLD</span></p>
//  SCSS

.past_way {
  span {
    position: relative;
    &:before {
      content: "";
      height: 1px;
      width: 100%;
      position: absolute;
      bottom: 0;
      left: 0;
      background-color: #EF5350
    }
  }
}

この書き方は慣れているので、特にどうとも思わないが、SCSS で書くとき階層が深くなるため、わかりにくくなりがち。

新しいやり方

//  HTML

<p class="new_way"><span>HELLO NEW WORLD</span></p>
//  SCSS

.new_way {
  text-decoration-line: underline;
  text-decoration-color: #EF5350;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.25em;
}

こちらの方法はシンプルだが、ブラウザの互換性が気になる。

都度、調査する必要があるかもしれない。

IE で クラスをtoggleさせるには

はじめに

以前、classList でクラスを操作する覚書をしたが、IE ではそのうちのtoggle() が使えない沼に一瞬だけハマった。

解決方法

classList の.add() と .remove() 、そして contains() をうまく使えば解決する。

// HTML
<p class="togglclassBtn">click me!</p>
<p class="change_color">HELLO!</p>
// SCSS
.togglclassBtn {
  display:inline-block;
  padding: 10px 20px;
  border-radius: 10px;
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
  background-color: #EF5350;
  color: #FFFFFF
}
.change_color {
  display:inline-block;
  padding: 10px 20px;
  border-radius: 10px;
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
  background-color: #FFFFFF;
  &.js-active {
    background-color: #1976D2;
    color: #ffffff;
  }
}
// JavaScript
const btn = document.querySelector('.togglclassBtn');
const target = document.querySelector('.change_color');

btn.addEventListener('click', function() {
  if(target.classList.contains('js-active')) {
    target.classList.remove('js-active')
  } else {
    target.classList.add('js-active')
  }
})

See the Pen toggleClass by IE by PROGBLOG (@progblog-sank) on CodePen.


IE で動作確認は上記をダウンロードする。

Nuxt.js で v-for について理解を深める

はじめに

webアプリを開発中に v-for についていまいち理解し切れていないと感じたので、じっくりと考えてみる。

なお、今回はCLI ではなく CDN にて動作確認をするので、すべてのソースに https://unpkg.com/vue@next を読み込んでいる。

まずは v-for ってなに

公式には下記のように書かれている。

v-for ディレクティブを使えばアイテムのリストを配列内のデータを使って表示することができます

で例として挙げられてるのが、下記のようなソース。

See the Pen v-for_Base by PROGBLOG (@progblog-sank) on CodePen.


確かに配列を使用してデータを呼び出してくれている。

ただこれだけ見ると、別にHTML にひとつひとつ書いていくのと決して変わらない。

むしろ面倒くさいと思うまである。

じゃあなぜ v-for を使用するのか

配列が動的に変化する場合は、非常に有効に作用する。

See the Pen JjRQyJw by PROGBLOG (@progblog-sank) on CodePen.


例えばこんな感じで、リストの増減する要素を簡単に作成することができる。

key属性 について

繰り返される DOM の内容が単純な場合や、性能向上のためにデフォルトの動作に意図的に頼る場合を除いて、可能なときはいつでも v-forkey 属性を与えることが推奨されます。

上記にあるように、v-for ではkey 属性を与えなければならない。

<ul>
  <li v-for="item in items" :key="item.id">...</li>
</ul>

vue のドキュメントにあるサンプルソースは上記の通り。

正直ここは理解しきれていないので、他サイトのまとめを拝借する。

  • keyVue の処理を手助けする
  • key がない場合、同じ要素を再利用される
  • key がある場合、key に基づいて変更される
  • 同じ要素を親に持つ場合key は一意なものにする
  • v-for のインデックスをkeyに用いない
  • key を正しく用いて効率よく扱っていきましょう。

tanks🥰: Vue.jsのkeyとは?-Vue.js

Nuxt.js の dataメソッド で Date が管理できなかった

はじめに

Firebase に送ったデータの管理でタイムスタンプが必要になったので、データの送信時に現在時刻を送れるようにした。

やったこと

<template>
    <input type="hidden" v-model="checkTime">
</template>
<script>
export default {
  props: ["user"],
  data() {
    return {
      chekTime: new Date(),
    };
  },
}
</script>

このコードだと管理ができない。

対処方法

今回はユーザー側に見えるデータではなく、あくまでもタイムスタンプとして使用するので形式は問わない。

そのため、Date.now() で管理することにして解決した。

Firebase のRealtime Database で取得した情報が重複しないようにする

はじめに

FirebaseRealtime Database から情報を取得し、 Nuxt.js の v-for で表示させた。

初回はうまく読み込みのだが、新しくデータを追加し、.on メソッドで呼び出したとき、今までのデータが1から呼び出され、過去のデータが2重に書き込まれた。

わかりにくいので、図のようにしてみる。

〇〇〇〇〇
×××××××××
△△△△△

☆☆☆☆☆ を追加すると

〇〇〇〇〇
×××××××××
△△△△△
〇〇〇〇〇
×××××××××
△△△△△
☆☆☆☆☆

となる。

これを解決したい。

こうなったコード

created: function() {
  firebase.database().ref(this.user.uid).on("value", (snapshot) =>{
    snapshot.forEach((childSnapshot) =>{
      let childData = childSnapshot.val();
      console.log(childData)
      this.details.push(childData);
    })
  })
},

.on() メソッドが発火されるたびに、実行される。

またvalue は下記の通り。

イベントの種類 value を使用しました。この種類のイベントは、データがほんの 1 か所変更されただけでも、Firebase データベース参照のコンテンツ全体を読み取ります。

つまり、何かを追加すると、Firebase データベース参照のコンテンツ全体を読み取り、表示される。

結果、前述の図のような事象が発生する。

コードと解決方法

  created: function() {
    // firebaseからデータを取得する(初回)
    firebase.database().ref(this.user.uid).once("child_added", (snapshot) =>{
      snapshot.forEach((childSnapshot) =>{
        let childData = childSnapshot.val();
        console.log(childData)
        this.details.push(childData);
      })
    })
    // firebaseからデータを取得する(初回以降)
    firebase.database().ref(this.user.uid).orderByValue().startAt(this.chekTime).on("child_added", (snapshot) =>{
      let childData = snapshot.val();
      this.details.push(childData);
    })
  },

解説

    // firebaseからデータを取得する(初回)
    firebase.database().ref(this.user.uid).once("value", (snapshot) =>{
      snapshot.forEach((childSnapshot) =>{
        let childData = childSnapshot.val();
        console.log(childData)
        this.details.push(childData);
      })
    })

まず1つ目の塊はほとんど前回のコードと変更なし、唯一の変更点は.on().once() に。

ただこれが非常に重要で、.once() は下記の通り。

once() メソッドを使用して、このシナリオを簡素化できます。このメソッドは 1 回トリガーされ、その後再びトリガーされることはありません。

つまり、最初の読み込み時のみの記述になる。

次の塊は2回目以降の処理になる。

    // firebaseからデータを取得する(初回以降)
    firebase.database().ref(this.user.uid).orderByValue().startAt(this.checkTime).on("child_added", (snapshot) =>{
      let childData = snapshot.val();
      this.details.push(childData);
    })

こちらは.on で都度都度データを取得する。

ただ前回のコードと違うのは、新規で追加されたデータだけを取得することができる点。

それを可能にしているのが、下記のコード。

.orderByValue().startAt(this.checkTime)

まず.orderByValue() は下記の通り。

orderByValue() を使用すると、子がその値で並べ替えられます。並べ替えの条件は、指定した子キーの値の代わりにノードの値が使用されるという点を除いて、orderByChild() の場合と同じです。

そして.startAt() は下記の通り。

startAt()endAt()equalTo() を使用すると、クエリに対し任意の始点と終点を選択できます。

この絞り込みにより初期化時(this.checkTime)*1以降に追加された要素に対してトリガーをするよう対象を絞り込むことができた。

*1:checkTime は投稿時にFirebase に保存しておく必要がある。

Firebase の push() で 自動でIDが付与された子要素の取得したい

はじめに

別記事にて記載したが、FirebaseRealtime Databasepush() した場合、自動でIDが付与される。

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

こんな感じでJSON が生成される。

謎の文字列は都度都度、変更するので法則性がない。

そこで、JSON の子要素を取得するときに困った。

子要素の取得方法

コード

created: function() {
firebase.database().ref(this.user.uid).once("value", (snapshot) =>{
  snapshot.forEach((childSnapshot) =>{
    let childData = childSnapshot.val();
    console.log(childData) 
  })
});

参考

Firebase Databaseからデータを取得する方法は? ウェブ上でデータリストを操作する