やりたいこと
nuxt.js(vue.js)にてAPIを叩いた時、意図しないタイミングでの押下防止したい。
ダイアログ表示・非表示を制御すれば良いが、画面ごとに手動で設定してやるのは骨が折れるし絶対漏れが出る。
- @nuxtjs/axiosドキュメント
This option shows a loading bar while making requests integrating Nuxt.js progress bar (see "loading" options in config.nuxt.js). This is active only in the browser, and when loading bar is enabled and available.
You can also disable the progress bar in specific requests using the progress option in an inline request configuration:
これはNuxt.jsのProgressBarを利用していると言っている…?
つまりNuxt.jsのProgressBarを改造すれば、axiosを呼び出した時のダイアログ表示も夢ではない!
結論
- 大体は公式に書かれてあるやり方でいい
- https://ja.nuxtjs.org/docs/2.x/configuration-glossary/configuration-loading/
- https://axios.nuxtjs.org/options/#progress
- ただfinish() と同じようにset(num)も設定してやる必要がある
- mounted()時は公式通りnextTickを併用するのが安定する
- https://develop365.gitlab.io/nuxtjs-2.8.X-doc/ja/api/configuration-loading/
環境(直接関係のあるモノだけ抜粋)
"dependencies": {
"@nuxtjs/axios": "^5.13.1",
"nuxt": "^2.14.12"
},
node:v14.15.5
本ドキュメント前提
vueおよびnuxtの設定をある程度知っていること
試作ProgressBar
start(),finish()が必須で、fail(error)とincrease(num)も一応付けておく。
- /components/LoadingProgress.vue(コンポーネント名は繋がっていれば何でも良い)
<template>
中略。ここがダイアログになる
</template>
<script>
export default {
data() {
return { loading: false, persent: 0 };
},
methods: {
start() {
this.persent = 0;
this.loading = true;
},
finish() {
this.persent = 0;
this.loading = false;
},
fail(error) {
this.persent = 0;
this.loading = false;
console.log(error);
},
increase(num) {
this.persent = parseInt(num);
}
}
};
</script>
このコンポーネントを用いてloadingを行う。
- nuxt.config.js
// Modules: https://go.nuxtjs.dev/config-modules
modules: ["@nuxtjs/axios"],
// https://ja.nuxtjs.org/docs/2.x/configuration-glossary/configuration-loading/
loading: '~/components/LoadingProgress.vue',
ローディング中コンポーネントとして利用するコンポーネント名を設定する。
- 利用画面
await this.$axios
.post( // APIのURLや引数とか
)
できた!
↓
動かない。Nuxt.jsのカスタムローディングとしては正常に動いているが、axios実行時無反応
@nuxtjs/axiosさんの中身を見てみる
- node_modules/@nuxtjs/axios/lib
const setupProgress = (axios) => {
if (process.server) {
return
}
// A noop loading inteterface for when $nuxt is not yet ready
const noopLoading = {
finish: () => { },
start: () => { },
fail: () => { },
set: () => { }
}
const $loading = () => {
const $nuxt = typeof window !== 'undefined' && window['$<%= options.globalName %>']
return ($nuxt && $nuxt.$loading && $nuxt.$loading.set) ? $nuxt.$loading : noopLoading
}
loadingがそもそも無かったり、functionであるsetが無かったりすると何も起こらないようだ。
→**set(num)**を入れてみる
- /components/LoadingProgress.vue
<template>
中略。ここがダイアログになる
</template>
<script>
export default {
data() {
return { loading: false, persent: 0 };
},
methods: {
set(num) {
this.persent = parseInt(num);
this.loading = true;
},
start() {
this.persent = 0;
this.loading = true;
},
finish() {
this.persent = 0;
this.loading = false;
},
fail(error) {
this.persent = 0;
this.loading = false;
console.log(error);
},
increase(num) {
this.persent = parseInt(num);
}
}
};
</script>
動いた!
他躓いたところ
mounted メソッドを利用したい場合、必ず this.$nextTick を利用してください。 $loading がすぐに利用できるとは限らないためです。
コレを見逃していたらmounted時に$loadingが働かずにおかしな挙動になる。