LoginSignup
0
3

More than 1 year has passed since last update.

Vue.jsでAPIのコールからレスポンスが返ってくるまでぐるぐるマークを出す

Last updated at Posted at 2021-06-11

はじめに

久しぶりの投稿すぎて、うまく書けるか分からないですが、
最近触っている Vue.js の投稿をしてみます。

やってみたこと

現在、Vue CLIでチャットアプリをつくっているのですが、そのアプリでチャンネル変更機能があります。
よくあるチャットアプリと同じイメージで、チャンネルを変更したら変更後のチャンネルのメッセージを取得します。
データ取得・画面表示はできたのですが、どうも操作感が悪いなーと思っていました。

ぐるぐるがなかったためです。

ぐるぐるを表示することで、表示の切り替えのタイミングがユーザーに分かりやすくなり、カクついた操作感は解消されます。また他のボタンを押されることを防ぐこともできます。

実際にぐるぐるを表示してみた

ezgif.com-gif-maker.gif

ぐるぐるは何を使ったか

ぐるぐる自体は Vuetify が用意してる Progress circular コンポーネントを使用しました。
https://vuetifyjs.com/ja/components/progress-circular/

どんな処理を入れたか

  1. ぐるぐるコンポーネントを作成
  2. ぐるぐるコンポーネントを読み込む
  3. ぐるぐる専用のストアを作成
  4. axiosのinterceptors内でぐるぐるを制御

ぐるぐるコンポーネントを作成

BaseLoading.vue
<template>
  <v-dialog v-model="flag" fullscreen>
    <v-container fluid fill-height class="loading_bg">
      <v-layout justify-center align-center>
        <v-progress-circular :indeterminate="true" size="64" color="accent" />
      </v-layout>
    </v-container>
  </v-dialog>
</template>
<script lang="ts">
import Vue from "vue";
import { Component, Prop } from "vue-property-decorator";

@Component({
  components: {},
})
export default class BaseLoading extends Vue {
  @Prop({}) public flag: boolean;

  constructor() {
    super();
    this.flag = false;
  }
}
</script>

1つbooleanの値をもち、その値で表示/非表示を切り替えるだけのコンポーネントです。
その値がどこからどのタイミングでpropされるかは後述します。

ぐるぐるコンポーネントを読み込む

全画面共通でサーバとの通信時はぐるぐるを表示したいため、コンポーネントの一番親?にあたるApp.vueで読み込みます。
ぐるぐるコンポーネントに渡すbooleanは、次に説明する、ぐるぐる専用のストアのstateを見ています。
つまり、このApp.vueではストアのstateが更新されたタイミングでぐるぐるコンポーネントにbooleanをpropすることができます。

App.vue
<template>
  <v-app id="inspire">
    <v-content>
      <router-view />
      <BaseLoading :flag="IsShow" />
    </v-content>
  </v-app>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import BaseLoading from "./components/BaseLoading.vue";
import LoadingStore from "./store/loading/index";

@Component({
  components: { BaseLoading },
})
export default class App extends Vue {
  constructor() {
    super();
  }

  get IsShow() {
    return LoadingStore.IsShow;
  }
}
</script>

ぐるぐる専用のストアを作成

中身はシンプルで、booleanのstateが1つと、そのstateに対するgetter/setter(mutation)のみ用意します。

loading/index.ts
import {
  Module,
  VuexModule,
  Mutation,
  Action,
  getModule,
} from "vuex-module-decorators";

import store from "..";

@Module({ dynamic: true, store, name: "loadingStore", namespaced: true })
class LoadingStore extends VuexModule {
  private isShow: boolean = false;

  @Mutation
  public setIsShow(flag: boolean) {
    this.isShow = flag
  }

  get IsShow(): boolean {
    return this.isShow;
  }
}
exort default getModule(LoadingStore);

axiosのinterceptors内でぐるぐるを制御

このアプリでは、Vueで非同期処理をするときの定番であるaxiosを使っています。
axios を利用した API の使用

axiosでは、interceptorsなるものが用意されており、APIコールのリクエスト直前とレスポンス直後の処理を入れることができます。

interceptors.ts
export default function setup() {

  axios.interceptors.request.use(async (config) => {
    LoadingStore.setIsShow(true)
    return config;
  });

  axios.interceptors.response.use(
    (response) => {
      LoadingStore.setIsShow(false)
      return response;
    },
    async (error: AxiosError) => {
      LoadingStore.setIsShow(false)
      }
  );
}

リクエスト直前

LoadingStore.setIsShow(true)

レスポンス直後

LoadingStore.setIsShow(false)

これで、APIの通信時のみぐるぐるを表示することができました。

今後の課題

1操作で1APIコールならこれで問題ないのですが、1操作で複数APIコールする箇所があり、この処理のままだと、ぐるぐるがチカチカする感じで少し違和感があります。
それはまた追々。。

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3