Skip to content

Instantly share code, notes, and snippets.

@orimajp
Last active November 5, 2021 12:40
Show Gist options
  • Save orimajp/36d83ef259cd46bdd55d56ebe13e93de to your computer and use it in GitHub Desktop.
Save orimajp/36d83ef259cd46bdd55d56ebe13e93de to your computer and use it in GitHub Desktop.
Nuxt.jsでサーバエラーメッセージをVuetifyのSnackbarに表示する方法

Nuxt.jsでサーバエラーメッセージをVuetifyのSnackbarに表示する方法

概要

Nxut.jsアプリでサーバエラーを共通的な画面表示の仕組みとして、UIフレームワークVuefityのSnackbarというコンポーネントを使ったエラー表示の実装方法について説明する。

なお、今回の実装方法はVuitifyに限らず利用可能と思われる。

実装方法

  1. サーバエラーメッセージを管理するためのmessageストア(Vuexによる実装)を用意
  2. axiosプラグインにおいて、エラーレスポンスからメッセージを拾ってmessageストアに格納する処理を実装
  3. エラー表示を行うSnackbarコンポーネントを用意し、messageストアの更新を監視し、メッセージが書き込まれたらSnackbarを表示する仕組みを実装

コードイメージ抜粋

store/message.js

メッセージを管理する専用のストアとして実装。

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')
  }
}

plugins/axios.js

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
    }
  })

}

components/ErrorSnackbar.vue

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>

layout/default.vue

レイアウトにて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が見ているという実装がややトリッキーに思える。

参考リンクなど

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment