基礎からメモ: Vue.js CH7-p252 Vuexの導入
Vuex は Vueアプリケーションで使うデータとその状態を一元管理する「状態管理」のための拡張ライブラリ。
深くネストされたコンポーネント構造では、コンポーネント間でprops
と$emit
を使って各コンポーネントどうしのやり取りをする必要があるが、Vuex を使えばデータ管理がしやすくなる。
Vuexのインストール
まず管理ツールの n で node と npm のバージョンアップから
$ node -v v10.10.0 # アップ前のバージョン $ n --lts 12.16.1 # 最新LTS版をインストール $ sudo n lts $ node -v v12.16.1 $ npm -v 6.13.4
練習用プロジェクト作成
$ vue init webpack my-app
$ cd my-app/
$ npm install
Vuex と babel-polyfill
をインストール
$ npm install vuex babel-polyfill
npm run dev
で開発用サーバを立ち上げ、ブラウザから localhost:8080 にアクセスして初期表示を出しておく。あとは構成ファイルを書き換えるたびにリロードなしで自動的に画面が更新される。ブラウザの開発ツールを表示しておけば、エラーなどもコードを書き換えるたびに出てくる。
シンプルなストア構造
Vuex が状態管理するためのストア(仮想のデータベースのような役割)を作成する。
my-app/src/
直下にstore.js
を作成
[src/store.js]
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++ } } }) export default store
state
オプションに定義されるのはアプリケーションで使用するデータ。これを定義し読み込むことで、このデータにアクセスできる。
ここにあるように Vuexインスタンス内では、Vueインスタンスと違い自身の保持するデータにthis
なしでアクセスできる。
したがってメソッド定義にアロー関数が使える。
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment: state => { state.count++ } } })
main.js
からsrc/store.js
を読み込み、store.state.count
を利用する。
パスの@
はデフォルトで定義されているsrc
ディレクトリのエイリアス。@
エイリアスが使えない場合はmain.js
からの相対パスで./store.js
でも問題ない。
[main.js]
import Vue from 'vue' import App from './App' import store from '@/store.js' Vue.config.productionTip = false // countを出力 console.log(store.state.count) // ミューテーションのincrementをコミットする store.commit('increment') // countの値が増えている console.log(store.state.count) new Vue({ el: '#app', render: h => h(App) })
ストアをVueアプリケーションに登録し共有する
この状態では各単一ファイルコンポーネントごとにstore.js
を読み込む必要があるが、main.js
でストアのインスタンスをVueアプリケーションのルートに登録することで、コンポーネントのインスタンスプロパティ$store
として全てのコンポーネントから利用できる。
[main.js]
new Vue({ el: '#app', store, // <= storeを登録 render: h => h(App) })
[src/App.vue の scriptタグ内]
import HelloWorld from './components/HelloWorld' export default { name: 'App', components: { HelloWorld }, created() { // countを出力 console.log(this.$store.state.count) // ミューテーションのincrementをコミットする this.$store.commit('increment') // countの値が増えている console.log(this.$store.state.count) } }
同じ出力指示をsrc/components/HelloWorld.vue
にも書いてみると、
[src/components/HelloWorld.vue]
export default { name: 'HelloWorld', data () { return { msg: 'Welcome to Your Vue.js App' } }, created() { // ミューテーションのincrementをコミットする this.$store.commit('increment') // countの値が増えている console.log(this.$store.state.count) } }
App.vue
とHelloWorld.vue
で incrementを2回コミットしているので、store.state.count
のコンソール出力は
0 → 1 → 2
となるはずだ。コンポーネント間でストアが共有されているのがわかる。