【Vue】Loading画面の実装方法を✅

脚に鉄アレイ入ってる?胸Bカップくらいある?と彼女に言われてすごく上機嫌な23期酒ケジュール作成中です。

進捗

多少の進捗あり!

Image from Gyazo

こちらの記事を参考にしてSSL対応にいたしました。

SSLとは

WebブラウザとWebサーバー間においてデータのやりとりを暗号化させる技術。Secure Socket Layerの略。

クレジットカード情報や個人情報などの秘匿情報が外部に漏れたり、ハッキングされたりすることを防ぐ。

SSL対応のサイトには、webブラウザの左側に南京錠マークが出る。また、http://ではなくhttps://になることも特徴とされている

TLS/SSL」と呼ばれることもある。SSLの方が先輩。

SSLの仕組み|情報セキュリティ関連の技術|基礎知識|国民のための情報セキュリティサイト

さて、今回はVue.jsを使ったアプリに「いい感じのloading中画面」とつける方法を学習していきたいと思います。

Loading画面とは

データを取ってくるまで表示させておく画面

サークルやボール、サイクロンなどの種類がある。決済中画面や電波の悪いときによく見る。

これって、画面がフリーズしてるの?それとも待ち時間なの?とユーザーを困惑させないための配慮として使われたりする。

Image from Gyazo

$ yarn add vue-loading-template

main.js

import Vue from 'vue';
import App from '../App';
import VueLoading from 'vue-loading-template';
Vue.use(VueLoading /** options **/);

これだけでもう使用できてしまう。

次に、ローディングを付与させたい画面に下記コンポーネントを記述する。

	<VueLoading
    type="cylon"
    color="#d9544e"
    :size="{ width: '50px', height: '50px' }"
  ></VueLoading>

任意でカスタマイズする事ができる

type:

ローディングの種類を変更させる事ができる。

cyclon

	<VueLoading
    type="cylon"
    color="#d9544e"
    :size="{ width: '50px', height: '50px' }"
  ></VueLoading>

Image from Gyazo

spiningDubbles

<VueLoading
	type="spiningDubbles"
	color="#d9544e"
	:size="{ width: '50px', height: '50px' }"
></VueLoading>

Image from Gyazo

spin

	<VueLoading
    type="spin"
    color="#d9544e"
    :size="{ width: '50px', height: '50px' }"
  ></VueLoading>

Image from Gyazo

color:

任意の色にする事ができる

#000

	<VueLoading
    type="spin"
    color="rgb(0,0,0)"
    :size="{ width: '50px', height: '50px' }"
  ></VueLoading>
[![Image from Gyazo](<https://i.gyazo.com/22214020b89ad57f3929872315c6db83.gif>)](<https://gyazo.com/22214020b89ad57f3929872315c6db83>)

size:

ローディング中画面の大きさを変更する事ができる

	<VueLoading
    type="spin"
    color="rgb(0,0,0)"
    :size="{ width: '200px', height: '50px' }"
  ></VueLoading>

Image from Gyazo

全体像

もしloadingCircleがtrueだった場合、VueLoadingが表示され、falseだった場合、酒ケジュールが表示されるようにしている。

コンポーネント

frontend/components/result/ShowShucheduleModal.vue

<div class="text-center black--text outer-layer" style="white--text">
                  <div v-if="loadingCircle">
                    <VueLoading
                      type="cylon"
                      color="#d9544e"
                      :size="{ width: '50px', height: '50px' }"
                    ></VueLoading>
                  </div>
                  <div v-else>
                    <img :src="drunknessEagerToImg" width="50" height="50" />
                  </div>
                  <span class="mb-6 text-center">への 酒ケジュール</span>
                </div>
                <br />
                <div v-if="loadingCircle">
                  <VueLoading
                    type="spiningDubbles"
                    color="#d9544e"
                    :size="{ width: '200px', height: '50px' }"
                  ></VueLoading>
                </div>
                <div v-else>
                  <v-row justify="center" align-content="center">
                    <v-col
                      v-for="data in alcoholItems"
                      :key="data.id"
                      class="justify-space-between outer-layer"
                    >
                      <v-icon>{{
                        data.alcohol_percentage === 0 ? 'mdi-cup' : 'mdi-glass-mug'
                      }}</v-icon>
                      <p>
                        {{ data.name }}
                      </p>
                      <p>{{ data.alcohol_percentage }}%</p>
                      <p>{{ data.alcohol_amount }}ml</p>
                    </v-col>
                  </v-row>
                </div>
<template>

</template>
<script>
import { VueLoading } from 'vue-loading-template';
export default {
props: {
alcoholDatas: {
      type: Array,
    },
    loadingCircle: {
      type: Boolean,
    },
  },
components: {
    VueLoading,
  },
computed: {
    alcoholItems() {
      const targetAlcohols = (this.alcohols = this.alcoholDatas);
      return targetAlcohols;
    },
  },
}
</script>

v-ifを使用し、loadingCircleがtrueの場合、VueLoadingが表示され、それ以外はfalseになるようにした。

loadingCircleがfalseになるタイミングは、親コンポーネントapiを叩いてデータを取ってくることが成功したタイミングになっている。

コンポーネント

frontend/pages/Result.vue

<template>
<div>
              <ShowShucheduleModal
                v-if="showShuchedule"
                :alcoholDatas="alcoholContents"
                :loadingCircle="loading"
                :motivationImg="nextMotivationImg"
                @twitterShare="snsUrl"
                @closeModal="closeShucheduleModal"
              />
              <div>
</div>
</template>
<script>
import { mapActions, mapGetters, mapMutations } from 'vuex';
export default {
components: {
    ShowShucheduleModal,
  },
data(){
loading: true,

},
created() {
    axios
      .get('/alcohols')
      .then((alcoholResponse) => {
        this.alcohols = alcoholResponse.data;
        return this.alcohols;
      })
      .then((alcohols) => {
        this.loading = false; ←ここでloadingをfalseにしている
        const thisAnalyze = this.analyzes;
        const targetValues = alcohols;
        const analyzeShuchedule = thisAnalyze[thisAnalyze.length - 1]['shuchedule'];
        const contentsOfTarget = Object.values(targetValues)[analyzeShuchedule];
        this.alcoholOrders = contentsOfTarget;
        this.alcoholContents = contentsOfTarget;
      });
  },
}
</script>

親子コンポーネントに分けているため、少々見づらいかもしれない。

ライフサイフルフックのcreatedメソッドの中にapiを叩く処理を記述することで、mountedに書いたときに比べてサーバーに対する負荷を軽減される。

非同期処理に順番をつける(Promise構文)axiosにより、alcoholsパスからalcoholを取得した後(.thenの中身)this.loadingがfalseになるように書いた。

このように記述することで、お酒の種類を取ってくるまではloadingをtrueにしておく事が可能になった。

完成図

<div v-if="loadingCircle">
                  <VueLoading
                    type="spiningDubbles"
                    color="#d9544e"
                    :size="{ width: '200px', height: '50px' }"
                  ></VueLoading>
                </div>
                <div v-else>
                  <v-row justify="center" align-content="center">
                    <v-col
                      v-for="data in alcoholItems"
                      :key="data.id"
                      class="justify-space-between outer-layer"
                    >
                      <v-icon>{{
                        data.alcohol_percentage === 0 ? 'mdi-cup' : 'mdi-glass-mug'
                      }}</v-icon>
                      <p>
                        {{ data.name }}
                      </p>
                      <p>{{ data.alcohol_percentage }}%</p>
                      <p>{{ data.alcohol_amount }}ml</p>
                    </v-col>
                  </v-row>
                </div>

Image from Gyazo

【Vue.js】ローディング画面の実装方法(サンプルコード付き) - Qiita