LoginSignup
5

More than 3 years have passed since last update.

posted at

[nuxt.js その7] グローバルsnackbarの実装

snackbarとは

以下の画像の赤枠で記しているメッセージボックスのことです。Vuetifyで用意されているのですぐに使用することができます。
snackbar.PNG

タイトルではグローバルsnackbarと銘打っていますがその名前が正しい表現なのかはわかってません。実体は、storeにsnackbar操作用のデータを用意して、そこにディスパッチすることで表示するsnackbarのことです。

snackbar.js (ストア)の実装

表示/非表示を表す値:isEnable
表示するメッセージ:message
を用意して、以下のように作成しました。

~/store/snackbar.js
export const state = () => ({
  isEnable: false,
  message: false
})

export const getters = {
  status: state => {
    return state.isEnable
  },
  message: state => {
    return state.message
  }
}

export const mutations = {
  setenable (state) {
    state.isEnable = true
  },
  setdisable (state) {
    state.isEnable = false
  },
  setMessage (state, message) {
    state.message = message
  }
}

export const actions = {
  snackOn ({commit}) {
    commit('setenable')
  },
  snackOff ({commit}) {
    commit('setdisable')
  },
  setMessage ({commit}, message) {
    commit('setMessage', message)
  }
}

実際に表示したい場合は以下のように呼ぶことで表示することができます。

vue.js
this.$store.dispatch('snackbar/setMessage', 'ログアウトしました')
this.$store.dispatch('snackbar/snackOn')

default.vueにsnackbarをセットしておく

操作用のストアはできたので、実際に表示される部分の実装をしていきます。
全体で1つのsnackbarを使用できるようにしたいのでレイアウトにあるdefault.vueに埋め込みます。

~/layouts/default.vue
    <v-snackbar
      top
      v-model='snackbarVisible'
    >
      {{ this.$store.getters['snackbar/message'] }}
    </v-snackbar>
    <v-content>
      <v-container>
        <nuxt />
     </v-container>
    </v-content>

snackbarVisibleをv-modelにセットして、これをcomputedにて実装しているのですが、ここで非常につまずきました。当初、this.$store.state.snackbar.isEnableをそのままv-modelにセットしたり、以下のようなcomputedの実装で試みましたが、ページをリロードしたタイミングでstoreの値が一時的にtrueに変わってしまい毎回snackbarが表示されてしまうといった動きになっていました。

vue.js
  computed: {
    // snackbarが自動でfalseに設定するためセッタを用意して、明示的にdispatchからOffするようにする
    snackbarVisible () {
        return this.$store.state.snackbar.isEnable
    }
  }

snackbarが設定された表示時間が経過すると自動的に表示のフラグをfalseに変えてくれる仕様のようなのですが、おそらくこれがうまく動いてなかったことで、上記のような動作になっているようでした。以下のようにsnackbarVisibleにゲッタとセッタを明示的に用意してあげることで解決しました。

vue.js
  computed: {
    // snackbarが自動でfalseに設定するためセッタを用意して、明示的にdispatchからOffするようにする
    snackbarVisible: {
      get() {
        return this.$store.state.snackbar.isEnable
      },
      set() {
        return this.$store.dispatch('snackbar/snackOff')
      }
    }
  }

セッタなしcomputedに戻すと以下のエラーメッセージが出てました。
[Vue warn]: Computed property "snackbarVisible" was assigned to but it has no setter.
セッタを用意しろ って書いてありますね。気づかなかった。。。

ひとまず、これでsnackbarの実装もできました。
何かユーザにメッセージを通知したい場合には簡単に表示できるようになりましたね。

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
What you can do with signing up
5