Nxut.jsアプリでサーバエラーを共通的な画面表示の仕組みとして、UIフレームワークVuefityのSnackbarというコンポーネントを使ったエラー表示の実装方法について説明する。
なお、今回の実装方法はVuitifyに限らず利用可能と思われる。
- サーバエラーメッセージを管理するためのmessageストア(Vuexによる実装)を用意
- axiosプラグインにおいて、エラーレスポンスからメッセージを拾ってmessageストアに格納する処理を実装
- エラー表示を行うSnackbarコンポーネントを用意し、messageストアの更新を監視し、メッセージが書き込まれたらSnackbarを表示する仕組みを実装
メッセージを管理する専用のストアとして実装。
export const state = () => ({
message: ''
})
export const getters = {
getMessage: (state) => state.message,
existsMessage: (state) => state.message !== ''
}
export const mutations = {
setMessage(state, message) {
state.message = message
},
clearMessage(state) {
state.message = ''
},
}
export const actions = {
setMessage( { commit }, message) {
commit('setMessage', message)
},
clearMessage( { commit } ) {
commit('clearMessage')
}
}
HTTPステータス400
でかつレスポンスにmessage
プロパティが存在する場合のみ、messageストアを更新する。
export default function ({$axios, redirect, store}) {
$axios.onError(error => {
if (!error.response) {
return
}
const code = error.response.status
if (code === 400) {
if (error.response.data === undefined) {
return
}
const message = error.response.data.message
if (message === undefined || message === null || message === '') {
return
}
store.commit('message/setMessage', message)
return
}
})
}
ErrorSnackbarコンポーネントを用意。
<template>
<v-snackbar
v-model="snackbar"
color="error"
auto-height
top
>
{{ getMessageText }}
<v-btn
dark
flat
@click="clearMessage"
>
Close
</v-btn>
</v-snackbar>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
data() {
return {
snackbar: false,
}
},
methods: {
...mapGetters('message', ['getMessage', 'existsMessage']),
...mapActions('message', ['clearMessage']),
},
computed: {
isShow() {
return this.existsMessage()
},
getMessageText() {
return this.getMessage()
},
},
watch: {
isShow: function () { // computedのisShow()を監視している
this.snackbar = this.existsMessage()
},
snackbar: function () { // タイマでスナックバーが閉じたときにメッセージをクリアする
if (!this.snackbar) {
this.clearMessage()
}
}
},
}
</script>
レイアウトにてErrorSnackbarコンポーネントを利用。
<template>
<v-app >
<ErrorSnackbar></ErrorSnackbar>
</v-app>
</template>
<script>
import ErrorSnackbar from '~/components/ErrorSnackbar'
export default {
components: {
ErrorSnackbar
},
}
</script>
ErrorSnackbarにおけるcomputedとwatchの使い方にイマイチ自信が無い。テンプレート内で未使用の算出プロパティisShow
を監視プロパティisShow
が見ているという実装がややトリッキーに思える。