2019/12/19入門者必読、vue.jsの状態管理Vuexがわかる本文書では、できるだけシンプルな例を通してVuexの説明を行っていきます。Vuexを使った経験がないという入門者の人また下記の図がわからないという人を対象にしています。Vuexが難しいなと感じている人がいるとすれば用語がこれまでのvue.jsよりも増えていることまた記述方法が長かったり短縮形によって複数の書き方があることが原因だと思います。一度理解していまえば難しいものではないので安心して読み進めてください。まとめVuexとはVuexはすべてのコンポーネントでデータを一元管理するための仕組みです。management(状態管理)という言葉で説明されているため最初は状態という言葉にこだわらずデータ共有管理という名前で考えたほうがわかりやすいかもしれません。Vuexがない環境ではコンポーネント間のデータの受け渡しには、propsや$emitによるイベントを利用して行います。コンポーネント間でのデータ受け渡しが頻繁に行われたり階層が増えてくるとporpsや$emitでのデータ管理が難しくなります。その問題を解決するための仕組みがVuexです。Vuexという一つの入れ物にデータを入れることでどこからでもVuex内のデータへのアクセスが可能になります。Vuexでのデータ管理のイメージvue-cliによるプロジェクトの作成vuexを使用する環境を構築するためにvue-cliを利用します。featuresでBableとVuexだけ選択してインストールを行います。あわせて読みたいこれでわかるはじめてのvue-clivue-cliを使用しない場合は、vueとは別にvuexをインストールする必要があります。npmを使っている場合は、package.jsonの中を見てvuexがインストール済みかどうか確認してください。VuexVuexを使った場合と使わない場合を比較しながらVuexの説明を行なっていきます。Vuexを表示させるためにsrcディレクトリのApp.vueファイルに下記を記述します。serveコマンドを実行後、ブラウザでlocalhost:8080にアクセスします。Vuexが表示されればvue.jsが正常に動作しています。Vuexを表示させます。vue-cliでインストールする際にVuexを選択したので追加設定を行うことなくVuexを使用することができます。storeディレクトリの下にあるindex.jsファイルを開き、stateにmessageを追加します。index.jsファイルの中にはstate以外にもmutations、actionsがありますがこれはのちほど説明を行います。Vuexのstateは各コンポーネントがdataプロパティと同じものだと考えてください。dataプロパティとは異なる点があるとすれば、Vuexのstateに追加することですべてのコンポーネントからアクセスが可能となる点です。dataはコンポーネントファイルの中で定義され、その中でのみ使えるデータを扱う時の名前、stateはVuexでデータを扱う時の名前と覚えてください。}}とすればアクセスできるものではなりません。App.vueからのアクセスするためには$store.state.messageと記述する必要があります。$store.state.messageは少し長いですが、$storeという大きな入れ物の中にさらにstateという入れ物があり、その中にmessageが入っているイメージを持つことができます。Vuexを表示することができています。Vuexこれまでの方法とVuexを利用した方法でmessageを表示することができました。ここまでの動作確認ではVuexを使うことでデータの処理が難しくなったという印象はないと思います。Vuexとこれまでの方法Vuexではデータを共有管理しているので、どのコンポーネントから同じようにアクセスすることができます。App.vue以外の他のコンポーネントからも同じようにアクセスできるか確認するためにsrc¥componentsディレクトリの中にHelloVuex.vueファイルを作成します。App.vueの子コンポーネントとして利用するためApp.vueファイルでimportを行います。}}</script>HelloVuex.vueファイルに下記を記述します。Vuexのmessageにアクセスする方法は子コンポーネントでも親コンポーネントでも同じ$store.state.messageです。アクセスの仕方を見てもVuexは独立したデータ保管場所であることがわかるかと思います。Vuexが2つ表示されます。stateにあるデータがどのコンポーネントからも同じ方法でアクセスすることができることが理解できました。}}を使って表示させるためにcomputedプロパティを利用することができます。Vuexが表示されたままの状態になります。Vue今後はcomputedプロパティを利用してVuexのstateへのアクセスを行います。stateのアクセス方法にはGettersというものもありますがそれは後ほど説明します。オブジェクトデータの表示(従来の方法)Vuexのデータへのアクセス方法の理解をさらに深めるためにVuex管理下のオブジェクトデータへのアクセス方法を確認します。従来の方法で説明を行い、その後Vuexを使った場合の方法を説明します。ユーザ情報が入ったusersオブジェクトを利用し、ユーザ情報をリスト化するといったシンプルなものです。従来の方法では、dataにusersオブジェクトを設定後にv-bindを使って子コンポーネントへdataを渡します。}</script>子コンポーネントUserListを作成し、propsを使って渡されたdataを受け取りv-forディレクティブで展開します。UserListコンポーネントはsrc¥componentsの下に作成します。}}</script>ブラウザには下記のようにユーザ一覧が表示されます。これまでの方法でユーザ一覧オブジェクトデータの表示(Vuexを利用)今度はVuexを利用してみましょう。usersオブジェクトをstore¥index.jsのstateに移動します。]}usersオブジェクトをVuexに移動させたので、App.vueファイルではusersオブジェクトが必要でなくなったので削除を行います。usersオブジェクトがないためv-bindも必要ありません。}</script>子コンポーネント側ではpropsではなくcomputedプロパティを使ってVuexのstateのusersにアクセスを行い、その値を元にユーザ一覧を表示することができます。}}</script>compotedプロパティを利用せず、v-forディレクティブ内のusersを$store.state.usersとしても表示される結果は同じになります。v-bindやpropsの記述がなくなったことからも先程のmessageの例よりもVuexを使う場合と使わない場合の違いが明確になりVuexのデータ管理がこれまでとは異なることが理解できたかと思います。Gettersの使い方の確認computedプロパティと同様の働きをするGettersの使用方法を確認します。computedプロパティを使ってageが30以下のユーザ情報のみ表示させます。30);}}ageが30以下の2名のユーザのみ表示されます。computedプロパティでfilterを使う次にGettersを利用して同じことを実行します。index.jsにgettersを追加し、ユーザリストの中からageが30以下のユーザ情報のみ表示させるコードを記述します。},})UserListコンポーネントの中で先ほど実行していた処理を削除し、gettersを使った処理に変更を行います。Gettersにはthis.$store.gettersでアクセスすることができます。this.$store.getters.users;}}ブラウザで確認するとGettersを利用する前と同じユーザリストが表示されます。gettersを利用してユーザリストを取得gettersをcomputedプロパティではなく下記のように直接記述しても結果は同じです。}})</li>computedプロパティだと記述したそのコンポーネント内でしか利用できません。他のコンポーネントで同じ処理を行いたい場合は同じコードをコンポーネント毎に記述する必要があります。Gettersを利用するとVuexのstoreの中に保存されているので、他のコンポーネントからも同じ方法で利用することができます。Vuex内にあるデータの更新方法Vuex管理下のstate(データ)へのアクセス方法とGettersの使い方がわかったので、次はVuexで管理されているstateの更新方法を確認します。store¥index.jsの中のstateにcountを追加し、その値を0とします。}})通常はコンポーネント内のメソッドを使ってデータ更新を行います。Vuexのstateの値もコンポーネントのmethodsに更新用のメソッドを追加し、下記のようにVuexのstateを直接実行するのではと思うかもしれません。Vuexのstateに対して直接更新することは可能ですが直接更新は行ってはいけません。//コンポーネントのmethods内で下記のように記述してもいい??this.$store.state.count++stateの更新を行うためには、mutations(ミューテーション)を使う必要があります。store¥index.jsにcountの数を増やすmutationsを追加します。mutationsの引数にはstateが渡されます。mutationsを含め聞き慣れない新しい名称が出てくるため最初は圧倒されますが、使ううちに慣れるものなので安心してください。mutateには変更という意味があり、その名詞形のmutationsが使われています。}})mutationsの追加が完了したらmutationsの実行方法を知っておく必要があります。mutationsはcommitを使って実行します。storeのstateを更新することができる唯一の方法がmutationsをcommitすることだと記載されています。commitを使ってmutationを実行this.$store.commit('increment')stateはmutationsを利用して更新することがわかったので、ブラウザ上にボタンを表示させクリックイベントを設定します。そのボタンをクリックするとmutationsのincrementメソッドが実行されcountの数字が1増えるというコードを追加します。コードは下記のようになりApp.vueファイルに記述します。}}</script>ブラウザ上に表示されているUPボタンを押すとcount数が1ずつ増えます。mutationをcommitしてcount更新mutationsはcommitで更新を行うだけではなくstateの状態の変化を追うことができます。stateの状態の変化を確認stateの状態の変化を確認するためにChromeのdevtoolを開いてVuexのアイコンをクリックします。devtoolでvuexを確認devtoolを開いたままUPボタンを押すとCountが増えるのと同時に実行したmutationsが増えていくのを確認することができます。このようにmutationsを介してstateの状態(値)の変化を追うことができます。mutationsの実行履歴stateの状態の変化が見れるだけではなく選択したmutationsまで戻ったり、選択したmutationsまでの処理を削除することもできます。mutationspayloadでmutationsに値を渡すcommitには値を渡すことができ、payloadと呼ばれます。先程はclickで1つ値が増えましたが、一度に10増やしたい場合は10をpayloadに設定するとVuexのmutationsに設定した値を渡すことができます。}mutation側でもpayloadを取得できるように引数を増やす変更が必要です。}これでボタンを押すと10アップするプログラムに変更できます。Actionsを使ってstateを更新Vuexでは通常のvue.jsのmethodsに対応するactions(アクション)が準備されています。actionsもmutationsのようにstateを更新するために使用されるのですが、大きく2つの違いがあります。actionsはstateを直接変更するのではなくmutationsを経由して(commit)stateを更新するactionsには非同期の処理を入れることができる1については先ほど使用したcountの例を使って説明を行います。countを更新したい場合はmutationsを使って行うことを説明しました。actionsを使う場合は、actionsの中でcommitを使ってmutationsを実行し、mutationsからcountを更新させます。stateの値をactionsで更新する場合は必ずmutationsを経由して行うことになります。下記がactionsを追加したコードです。actionsの中でcommitの引数にmutationsのメソッドが入っていることがわかります。actionsでは引数にcontextというオブジェクトが渡されます。function(context){context.commit('increment')}}contexはstoreインスタンスが持つプロパティ、メソッドを保持するオブジェクトです。context.state.countでcountの値を取得することもできます。gettersメソッドを使うことができます。actionsの追加が完了したので、App.vueファイルのincrementメソッドを更新します。incrementメソッドからactionsを実行します。mutationsを実行するのはcommitでしたがactionsを実行するためにはdispatchメソッドを使用します。},actionsの追加後も先ほどと同様にブラウザ上のボタンをクリックするとcountの数が1ずつ増えます。actionsを追加してcount更新actionsにはビジネスロジックを記述し、mutationsではstateを更新する処理を記述します。コンポーネントのmethodsからcommitを使ってmutationsを実行するのではなくシンプルな処理でもactionsを通してmutationsを実行することが推奨されているようです。actionsの中では複数のmutationsを実行することも別のactionsを呼ぶことも可能です。contextの中でcommitしか使わないのであればES6のDestructuringを使って下記のように短縮して記述することも可能です。function({commit}){commit('increment')}}(2)についてですが、actionsには非同期の処理を入れることができるということはmutationsには非同期処理を入れることができないということを意味します。実際にはmutationsに非同期処理は入れても動作するので、mutationsでは非同期処理を入れないというのが正しい説明です。stateもmutationsを使わず直接更新ができたようにactionsでもstateを直接更新ができないわけではありません。Vuexは複数のコンポーネントから共有されていることもあり、同時に複数からの処理を正確に処理するためには守らなければいけないルールがあると認識しておく必要があります。Actionsの非同期処理とは非同期処理というのはaxiosを使ってサーバからデータを取得するような場面で頻繁に使われる処理です。非同期処理のイメージをもってもらうためにsetTimeout関数を使うと下記のような処理になります。3秒後にmutationsのincrementが実行されcount数が1増えます。}},axiosを使って非同期でデータを取得axiosを使って非同期でデータを取得する流れの中でどのようにActionsとMutationsが利用されるのか確認しておきます。これを見るとActionsの中で非同期処理を入れることとMutationsの中に入れないことが理解できると思います。axiosがインストールされていない場合はnpmコマンドでインストールを行います。axios実際にデータを取得したほうが実践的だと思いますので、無料サービスJSONPlaceholderを利用します。https://jsonplaceholder.typicode.com/usersにアクセスするとユーザ一覧を取得することができます。あわせて読みたいvue.jsを使ってaxiosを学ぶインストールしたaxiosを利用するためにstore¥index.jsファイルの上部でaxiosのimportを行います。'axios'store¥index.jsファイル内のactionsでaxiosを使って非同期でユーザ一覧を取得します。下記の中で非同期処理で取得したデータをcommitでmutationsのsetUsersを実行しています。}},mutationsでsetUsersを追加します。setUsersでは非同期処理は行わずただpayloadで受け取ったユーザデータをstateのusersに入力しているだけです。}},store¥index.jsに記述した全体は下記のようになります。},})次にApp.vueファイルからdispatchでactionsのgetUsersを実行します。}}</script>ブラウザで確認するとユーザ一覧が表示されます。ユーザ一覧の表示この動作確認から非同期処理が含まれたActionsとstateの更新処理を同期処理で行うmutationsについて理解することができました。本文書で動作確認に利用したコード本文書で最終的に作成したコードは下記の通りです。Stateの説明をすべて行いました。下記の図が理解できていればVuexの概念はほぼ理解できていると思います。理解を確認するため、文書の中で度々出てきたcountの例を元に下記の図の流れを追ってみましょう。ユーザがボタンをクリックするとclickイベントによりローカルメソッドが実行され、そのメソッドの中でdispatchメソッッドが実行されます。dispatchによりActionsが実行され、Actionsの中のcommitメソッドによりmutationsが実行されます。mutationsはstateであるcountの値を変更します。アップされた値は、ブラウザに再描写され、ユーザはアップしたcountの値を確認することができます。mapActionsの理解も必要です。下記の文書を参考にしてください。