[NuxtJS]Vuetifyでダークモードとライトモードをスイッチで切り替えてみる

普段業務系のシステム開発でNuxtVuetifyでフロントエンドの開発をしてるんですが、業務系だとあんまりダークモードってやつを使わずシンプルにライトモードのみで開発を進めていくんですが、やっぱり状況に応じてダークモードとライトモードを切り替えられた方が良いかと思い、ダークモードとライトモードを画面上で切り替える機能を実装してみました。

ダークモードだとディスプレイの消費電力を抑えることができたり、目に優しいといった利点があるので、ダークモードとライトモードを画面側でユーザが切り替えられるのは良いかもしれません。

前提条件

  • nuxt: ^2.15.8
  • vue: ^2.6.14
  • vuetify: ^2.6.1

必要な実装

今回、ダークモードを実装するにあたり必要な実装は以下の通りです。

  • ダークモードのテーマを設定する
  • 状態管理(store)の機能でテーマの状態管理を行う
  • 画面側でテーマの切り替え機能を作る

ダークモードのテーマを設定する

nuxt.config.jsの「vuetify」を下記のように設定します。

  vuetify: {
    customVariables: ['~/assets/variables.scss'],
    theme: {
      dark: false,
      themes: {
        dark: {
          primary: colors.blue.darken2,
          accent: colors.grey.darken3,
          secondary: colors.amber.darken3,
          info: colors.teal.lighten1,
          warning: colors.amber.base,
          error: colors.deepOrange.accent4,
          success: colors.green.accent3
        }
      }
    }
  },

ここでダークモードのテーマで使用するカラーを設定しています。

状態管理(store)の機能でテーマの状態管理を行う

storeディレクトリに「index.js」を追加し、下記のように実装します。

export const state = () => ({
  theme: false
});

export const mutations = {
  theme(state, theme) {
    state.theme = theme
  }
}

export const actions = {
  theme({
    commit
  }, theme) {
    commit('theme', theme)
  }
}

theme」という変数を使用し、ダークモードとライトモードの切り替えを判別します。

画面側でテーマの切り替え機能を作る

v-switchで「theme」の値の切り替えを行い、その変更を「watch」で検知し、「this.$vuetify.theme.dark」に対して、v-switchで切り替えた後のthemeの値を設定します。これでダークモードとライトモードの気鋭かえができるようになります。

<template>
  <app>
    <v-icon v-if="theme" class="mx-2">mdi-weather-night</v-icon>
    <v-icon v-else class="mx-2">mdi-white-balance-sunny</v-icon>
    <v-switch v-model="theme" hide-details></v-switch>
  </app>
</template>

<script>
export default {
  data() {
    return {
      theme: this.$store.state.theme,
    }
  },
  watch: {
    theme() {
      this.$store.dispatch("theme", this.theme)
      this.$vuetify.theme.dark = this.theme;
    }
  },
}
</script>

最後に

Vuetifyを使うことでかなり簡単にダークモードとライトモードの切り替えを行うことができました!今回のダークモードとライトモードの切り替えはpagesの個々のページに実装するのではなく、layoutsの方で共通的なレイアウトとして実装した方が良さそうですね。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です