完全な手順!Vueでajaxローディング表示する3ステップ

さてさて、最近Laravelの話題ばかりを投稿してることに気がついたので今回は地味に必要になってくるAjaxローディングの「終わるまで少し待ってね」表示をVueを使って実装する方法を3ステップでわかりやすくお届けしたいと思います。

ローディングgifアニメーションをダウンロードする

みなさんもどこかのサイトで見たことがあると思いますけど、私は以下のような「今頑張ってやってます」のことをローディングgifと呼んでいます。

 ←これ

こういうgifアニメーションって、もちろん自分でも作成することは可能ですが、なんせ時間がかかってしまいますし、きれいなものを使いたい場合はデザイナーさんに頼まないといけなかったりします。

でも、もっとライトな感じでちょこっと使いたいんだよなー、という場合には私がいつもお世話になっているおすすめのサイトがあります。

それが、「ajaxload.info」です。

このサイトは英語サイトですが、誰でも簡単にローディングgifを作成することができます。

では、実際にひとつ作ってみましょう。

ローディングgifのデザインを選ぶ

Indicator typeと書かれている部分がローディングgifのデザインを選ぶセレクトボックスになっています。クリックして好きなものを選んでください。

背景色を選ぶ

次にローディングgifの背景色を決める部分です。「Background color」の部分で好きな背景色を選ぶか、Transparent backgroundを選んで透明にしましょう。

ローディングgifの色を選択する

次にローディングgif自体の色を選択します。(ここでは赤を選択しました)

ローディングgifを作成してダウンロードする

あとは、「Generate it !」ボタンでgifアニメーションを作成し、「Download it !」ボタンダウンロードしましょう。

ajaxload.infoのライセンスは自由度が高い

こういうフリー素材のサイトではたまにGPLライセンスやApache2.0ライセンスの場合がありますが、ajaxload.infoではWTFPLライセンスを採用しています。

WTFPLライセンスは、パブリックドメインと同等のライセンスのため非常に使いやすいです。(名前自体も「You、あんたが使いたいようにやっちゃいなよ」ライセンスです ^^)

※WTFPLライセンスの詳細はウィキペディアでご覧ください。

Vueコンポーネントをつくる

では、次にダウンロードしたローディングgifを表示するVueコンポーネントを作っていきます。

コンポーネントのコード

もちろんimgタグで直接表示して、v-ifなどで切り替えることでもOKですが、ローディングgifは再利用することが多いと思いますので、以下のような専用のVueコンポーネントを作成しておくことをおすすめします。

Vue.component('v-loading', {
    props: {
        text: {
            default: 'ロード中...',
            type: String
        },
        show: {
            default: false,
            type: Boolean
        }
    },
    template: '<div v-if="show"><img src="/images/ajax-loader.gif">&nbsp;<span v-text="text"></span></div>'
});

使い方は、

<v-loading></v-loading>

となりますがデフォルトでは何も表示されません。

もしローディングを表示したい場合は、

<v-loading show="true"></v-loading>

という具合に、showtrueにしてください。

また、

<v-loading text="現在アップロード中です..."></v-loading>

というように、表示したいテキストをその都度変更することができます。

実際の表示例はこうなります。

全サンプルコード

今回コンポーネントを作ってローディングgifを表示してみたサンプルコードは以下になります。vue.jsはcdnを使っているので問題ないですが、「/images/ajax-loader.gif」の部分は適時ご自身の環境に合わせてください。

<html>
<body>
<div id="app">
    <v-loading show="true" text="現在アップロード中です..."></v-loading>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script>

    Vue.component('v-loading', {
        props: {
            text: {
                default: 'ロード中...',
                type: String
            },
            show: {
                default: false,
                type: Boolean
            }
        },
        template: '<div v-if="show"><img src="/images/ajax-loader.gif">&nbsp;<span v-text="text"></span></div>'
    });

    new Vue({
        el: '#app'
    });

</script>
</body>
</html>

使い方の実例

ではここからは、Ajax通信も含めた実例を紹介していきたいと思います。Ajax通信にはaxiosを使います。

HTML部分

<div id="app">
    <button type="button" @click="submit" v-if="!show">送信</button>
    <v-loading :show="show"></v-loading>
</div>

まず送信イベントを実行するためにbuttonタグを追加し、さらに送信されているときはこのボタンが表示されないようにv-ifを設定しています。

さらに、v-loadingタグではshowプロパティをリアルタイムで変更するために:show(つまり「v-bind:show」と同じ)としています。

Vue本体の部分

new Vue({
    el: '#app',
    data: {
        show: false
    },
    methods: {
        submit: function() {

            var self = this;
            this.show = true;

            axios.get('/ajax/your-url')
                .then(function(response){

                    // 成功時

                })
                .catch(function(error){

                    // 失敗時

                })
                .then(function(){

                    self.show = false;  // 最終的に必ず実行

                });

        }
    }
});

まず、重要なのがdataの中にローディングgifを表示するしないを判断するための変数showを追加しています。デフォルトではfalseなので表示はされません。

そして、ボタンが押されたらすぐsubmit()内でshowtrueに変更することでローディングを表示。その後2つ目のthen()は必ず通ることになるので、ajax通信が終わったら必ずローディング表示は終了するようになっています。

また、then()内のshowが「this.show」ではなく、「self.show」となっているのはfunctionの中ではスコープが違うため参照ができないことへの対処です。

これを実行すると、デフォルトではボタンだけが表示されていて、

クリックすると、

ローディングgifが表示され、ajax通信が終了すると、

また元のボタンだけ表示されるようになります。

実際の全コード

<html>
<body>
<div id="app">
    <button type="button" @click="submit" v-if="!show">送信</button>
    <v-loading :show="show"></v-loading>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<script>

    Vue.component('v-loading', {
        props: {
            text: {
                default: 'ロード中...',
                type: String
            },
            show: {
                default: false,
                type: Boolean
            }
        },
        template: '<div v-if="show"><img src="/images/ajax-loader.gif">&nbsp;<span v-text="text"></span></div>'
    });

    new Vue({
        el: '#app',
        data: {
            show: false
        },
        methods: {
            submit: function() {

                var self = this;
                this.show = true;

                axios.get('/ajax/your-url')
                    .then(function(response){

                        // 成功時

                    })
                    .catch(function(error){

                        // 失敗時

                    })
                    .then(function(){

                        self.show = false;  // 最終的に必ず実行

                    });

            }
        }
    });

</script>
</body>
</html>

※コンポーネントのときに書いたローディングgifのURLだけは同様に気をつけてくださいね。

終わりに

ということで、今回は短いですがajaxのローディングにフォーカスした記事をお届けしました。

参考にしていただけたら嬉しいです。

ではでは!