コラム

[Vue.js]Vuexで状態を管理する

Webシステムを作成しているとログイン状態の維持、検索条件の維持等、状態の管理をすることが多々あります。
そのような時にVuexというVue.jsのプラグインを使うと簡単に実装する事が可能です。
今回はVuexを使用して状態の管理をしてみたいと思います。

開発環境

Windows10 Enterprise
npm 8.1.2
node 16.13.2

プロジェクト作成

・プロジェクト作成

#vuex-sampleという名称のプロジェクト作成
vue create vuex-sample

プロジェクト作成種類を選択

#マニュアル作成を選択( Manually select featuresを選択 )
? Please pick a preset: (Use arrow keys)
> Default ([Vue 2] babel, eslint)
  Default (Vue 3) ([Vue 3] babel, eslint)
  Manually select features

・使用プラグイン等を選択

#RouterとVuexへのチェックを追加
? Please pick a preset: Manually select features
? Check the features needed for your project:
 (*) Choose Vue version
 (*) Babel
 ( ) TypeScript
 ( ) Progressive Web App (PWA) Support
>(*) Router
 (*) Vuex
 ( ) CSS Pre-processors
 (*) Linter / Formatter
 ( ) Unit Testing
 ( ) E2E Testing

後はVue RouterでSPAのルーティング制御の際と同様に選択

・動作確認

インストールが完了したらとりあえず動かし見ます。

cd vuex-sample
npm run serve

コマンド起動後 http://localhost:8080 にアクセス。

以上の様な画面が表示されていれば正常にプロジェクト作成が完了してます。

上記のプラグインだけだとリロード時に保管したデータが消えてしまうのでvuex-persistedstateというプラグインをインストールする必要があります。

npm install --save vuex-persistedstate

実際に使ってみる

今回は簡単な画面を作成してVuexの使用方法を説明していきます。

作成画面イメージ

画面は以下の様な3つの画面を用意し、入力した値をVuexを使用して管理してみます。
入力画面1、2で入力した値を確認画面で表示する簡単な画面です。

ディレクトリ構成

vuex-sample/
           ├─ node_modules/
           ├─ public/
           ├─ src/
           ├─ assets/
                ├─ components/
                ├─ store/
                ├─ router/
                ├─ views/
           ├─ babel.config.js
           ├─ package.json
           ├─ package-lock.json
           ├─ README.md

・storeディレクトリにはindex.jsを作成し、vuexの使用設定部分を記述する。
・routerディレクトリにはindex.jsを作成し、vue routerの使用設定部分を記述する。
・viewsディレクトリには画面用のコンポーネントを管理するディレクトリ。
・assetsとcomponentsは今回は使用しない。

実装

・main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router' ①
import store from './store' ②

Vue.config.productionTip = false

new Vue({
  router, ③
  store, ④
  render: h => h(App)
}).$mount('#app')

①でルーティング部分の実装ディレクトリを宣言し、③でVueで使用出来るようにしています。
②で状態管理の実装ディレクトリを宣言し、④でVueで使用出来るようにしています。

・App.vue

<template>
  <div id="app">
    <router-view/> ①
  </div>
</template>

<style>
・・省略
</style>

①の箇所はパスに紐づく画面を表示する場所です。この記述が無いと画面コンポーネントの内容は表示されません。

・router/index.js

Vue Router使用宣言、ルーティング定義やその他設定を行います。

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/entry01', ①
    name: 'Entry01',
    component: () => import(/* webpackChunkName: "entry01" */ '../views/Entry01.vue')
    
  },
  {
    path: '/entry02', ②
    name: 'Entry02',
    component: () => import(/* webpackChunkName: "entry02" */ '../views/Entry02.vue')
  },
  {
    path: '/confirm', ③
    name: 'Confirm',
    component: () => import(/* webpackChunkName: "confirm" */ '../views/Confirm.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

① 入力画面1用のルーティング設定。views/Entry01.vueを使用します。
② 入力画面2用のルーティング設定。views/Entry02.vueを使用します。
③ 確認画面用のルーティング設定。views/Confirm.vueを使用します。

・store/index.js
Vuex使用宣言、状態管理用の設定を行います。

VuexではVuex.Storeというクラスを生成しますが、プロパティaction、mutations、stateを実装する必要があります。
これら3つと画面の関係を図で表現すると次のようになります。



Vue Component(画面等)からアクションに状態管理をします。
アクションは状態を変更するのではなく、ミューテーションをコミットします。
ミューテーションではステートに対して状態の変更を行います。
変更されたステートはVue Componentでも有効となります。

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex)

export default new Vuex.Store({
  state: { ①
    input1: '',
    input2: ''
  },
  mutations: { ②
    setInput1: function(state, value) {
      state.input1 = value
    },
    setInput2: function(state, value) {
      state.input2 = value
    }
  },
  actions: {   ③
    setInput1: function(context, value) {
      context.commit('setInput1', value)
    },
    setInput2: function(context, value) {
      context.commit('setInput2', value)
    }	
  },
  
  plugins: [createPersistedState( { ④
  }
  )]  
})

① stateの設定。input1には入力画面1の値、input2には入力画面2の値を管理します。
② mutationsの設定。setInput1は入力画面1の値を設定するメソッド、setInput2は入力画面2の値を設定するメソッドを実装します。引数のstateはstateインスタンス、valueはactionsから渡される値が引数として渡されます。
③ actionsの設定。setInput1は入力画面1の値を設定するメソッド、setInput2は入力画面2の値を設定するメソッドを実装します。
引数のcontextはmutationsを呼び出す為のクラスのインスタンス、valueは画面から渡される値が引数として渡されます。
④ リロードしてもvuexで管理している値が消去しないようにするため、vuex-persistedstateをimportしてpluginsプロパティに渡します。(この例では空ですが、他にも幾つか機能の設定をする事が出来ます。)
この記述がないとリロードした際にはvuexの値はクリアされてしまいます。

・views以下

画面用のコンポーネントを配置します。以下のファイルを実装します。
・Entry01.vue:入力画面1用のコンポーネント
・Entry02.vue:入力画面2用のコンポーネント
・Confirm.vue:確認画面用のコンポーネント

Entry01.vue

<template>
	<div class="view-div">
		<h2>入力画面1</h2>
		<input type="text" v-model="input1"><br/> ①
		<button v-on:click="next">次へ</button>
	</div>
</template>

<script>
	export default {
		name: 'Entry01',
		data: () => ({
			input1 : '' ②
		}),
		mounted () {
			this.input1 = this.$store.state.input1 ③
		},
		methods: {
			next: function(){
				this.$store.dispatch('setInput1', this.input1) ④
				this.$router.push( "/entry02" ) ⑤
			}
		}
	}
</script>

① 入力テキストボックス input1変数と関連付けています。
② 画面で管理するデータを定義。入力テキストボックスと関連付けています。
③ mounted時に画面vuexで定義したstateのinput1の値を②で定義した変数に設定しています。
④ 次へボタン押下時にvuexのsetInput1アクションを実行。引数はinput1変数を指定します。ここでvuexでinput1の値を設定しています。
⑤ entry02(入力画面2)へ画面遷移します。

Entry02.vue

<template>
	<div class="view-div">
		<h2>入力画面2</h2>
		<input type="text" v-model="input2"><br/>
		<button v-on:click="next">確認</button>		
	</div>
</template>

<script>
export default {
  name: 'Entry02',
  data: () => ({
	input2 : ''
  }),
  mounted () {
	  this.input2 = this.$store.state.input2
  },
  methods: {
	  next: function(){
		  this.$store.dispatch('setInput2', this.input2)
		  this.$router.push( "/confirm" )
	  }
  }
}
</script>

Entry01.vueと同じような実装です。
変数名、アクション名、画面遷移先が違うだけなので説明は割愛します。

Confirm.vue

<template>
	<div class="view-div">
			<h2>確認</h2>
			input1:{{ $store.state.input1 }}<br/> ①
			input2:{{ $store.state.input2 }} ②
	</div>
</template>

① vuexのstateのinput1を表示しています。
② vuexのstateのinput2を表示しています。

管理方法の種類

vuexのデータ管理はLocalStorageでの管理とSessionStorageの管理の2種類があります。これはHTML5のAPI
Web Storageを利用してます。デフォルトだとLocalStorageを使用します。

・LocalStorage

永続的に有効で、ブラウザを再起動しても値は保存された状態です。

・SessionStorage

ウィンドウ・タブを閉じるまで有効で、ブラウザを再起動した際は値は消去されます。

SessionStorageを使用する際の設定は以下の様になります。


import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex)

export default new Vuex.Store({
  ・・・省略
  
  plugins: [createPersistedState( {
    storage: window.sessionStorage  
  }
  )]  
})

pluginsのcreatePersistedStateのstorageプロパティに「window.sessionStorage」を指定します。

以上でvuexの説明を終わりたいと思います。
vuexはまだ記述方や機能など色々あるので、後に記事にしていきたいと思います。
今回使用したソースコードはから取得できます。

続けてお読みください

開発の醍醐味

この記事をシェアする
  • Facebookアイコン
  • Twitterアイコン
  • LINEアイコン

お問い合わせ ITに関するお悩み不安が少しでもありましたら、
ぜひお気軽にお問い合わせください

お客様のお悩みや不安、課題などを丁寧に、そして誠実にお伺いいたします。

お問い合わせ
お電話でのお問い合わせ 03-5820-1777(平日10:00〜18:00)
よくあるご質問