見出し画像

Vue.js勉強記録その26 Vue3を更にパワーアップしよう 5-3 ver1

こちらの書籍で勉強中です。

今回は、vuexというものを使います。どうやら、データを格納しておくことのできる場所のようです。

■Vuexによる状態管理

・Vuexのインストール

まず、Vuexをインストールしていきます。CDNで読み込むことも出来るらしいけど、今回はnpmを使ってインストールしていきます。

npm install vuex@next


・Vuexの基本

Vuexは、「ストア」と呼ばれる物を使ってデータを管理します。そのためには、それ専用のファイルを作る必要があります。

また、各コンポーネントからストアへアクセスし値を取得するには、$storeという、Vuexのオブジェクトを使います。


・使ってみる

srcフォルダの中に、store.jsを作り、以下のように記述します。

import { createStore } from 'vuex'
export const store = createStore({
   state() {
       return {
           message: 'This is store data.'
       }
   }
})

まずは、importを使ってvuexからcreateStore関数を読み込みます。その後、その関数を使っていきます。使い方は、以下のような感じです。

export const store = createStore(引数)

引数には、ストアに関する情報が入ります。そしてそれを定数に代入し、そのままexportすることで、外部からアクセス出来るようにしています。

引数には、オブジェクトが入るのですが、まずstateというメソッドを用意します。その中で、必要なデータをオブジェクトの形で書き、returnしてあげます。

今回は、{message: 'This is store data.'}を用意しています。

では、messageをコンポーネント側で利用してみます。

まずは、main.jsを書き換えます。

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
import { store } from './store.js'

createApp(App).use(store).mount('#app')

store.jsをimportします。さらに、mountする前に、use(store)で、storeを使えるようにします。


次にApp.vueを書き換えます。

<template>
 <HelloWorld />
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
 name: "App",
 components: {
   HelloWorld,
 },
};
</script>

HelloWorldを出力するだけのシンプルな形になっています。


HelloWorld.vueを書き換えます。

<template>
 <div class="alert alert-primary">
   <h1>{{ data.title }}</h1>
   <p class="mt-3 h5">{{ $store.state.message }}</p>
 </div>
</template>

<script>
import { ref, reactive } from "vue";
export default {
 setup(props) {
   const data = reactive({
     title: "Vuex",
   });
   return { data };
 },
};
</script>

<p class="mt-3 h5">{{ $store.state.message }}</p>
この部分で、messageを出力しています。
$storeが、ストアに保管された値がまとめられているオブジェクトで、その中のstateにある、messageを取り出しています。

スクリーンショット 2022-03-15 0.03.52

ブラウザで見るとこんな感じです。


■ストアの中のステートの値を操作する

直接$store.stateの値を書き換えるのは、推奨されていないらしく、ミューテーションと呼ばれる、値を操作するための処理を用意する。

mutations:{
    名前:(引数)=>{
        処理内容
    },
    ・・・必要なだけ用意・・
}

こんな感じの書き方です。


store.js

import { createStore } from 'vuex'
export const store = createStore({
   state() {
       return {
           message: 'This is store data.',
           counter: 0
       }
   },
   mutations: {
       count: (state) => {
           state.counter++;
       },
       reset: (state) => {
           state.counter = 0;
       }
   }
})

countとresetというミューテーションを用意します。
各々、stateのcounterの値を変更する記述が書かれています。


コンポーネント側でミューテーションにアクセスするには、

$store.commit('名前')

こんな感じでアクセスします。


HelloWorld.vue

<template>
 <div class="alert alert-primary">
   <h1>{{ data.title }}</h1>
   <p class="mt-3 h5">{{ $store.state.message }}</p>
   <hr />
   <div
     class="btn btn-secondary"
     @click="$store.commit('count')"
     @click.shift="$store.commit('reset')"
   >
     <a class="h5"> clicked:{{ $store.state.counter }} </a>
   </div>
 </div>
</template>

<script>
import { ref, reactive } from "vue";
export default {
 setup(props) {
   const data = reactive({
     title: "Vuex",
   });
   return { data };
 },
};
</script>
   <div class="btn btn-secondary"
     @click="$store.commit('count')"
     @click.shift="$store.commit('reset')"
   >く

クリックするとcountを呼び出し、shiftキーを押しながらクリックするとresetを呼び出します。

なお、@clickは、v-on:clickと同じ意味です。


スクリーンショット 2022-03-15 0.33.30

ブラウザで見ると、ボタンを押すと数字が増えていき、shiftキーを押しながらクリックすると0に戻ります。


・ミューテーションに引数を渡す

ミューテーションに引数を渡すことも出来ます。

store.js

import { createStore } from 'vuex'
export const store = createStore({
   state() {
       return {
           message: 'This is store data.',
           counter: 0
       }
   },
   mutations: {
       count: (state, n) => {
           state.counter += n;
       },
       reset: (state) => {
           state.counter = 0;
       }
   }
})

countの所を以下のように直しています。

count: (state, n) => {
    state.counter += n;
},


HelloWorld.vue

<template>
 <div class="alert alert-primary">
   <h1>{{ data.title }}</h1>
   <p class="mt-3 h5">{{ $store.state.message }}</p>
   <hr />
   <div
     class="btn btn-secondary w-100"
     @click.exact="$store.commit('count', 1)"
     @click.shift="$store.commit('count', 2)"
     @click.alt="$store.commit('count', 3)"
   >
     <a
       class="h5 text-white text-decoration-none"
       @click.stop="$store.commit('reset')"
     >
       clicked:{{ $store.state.counter }}
     </a>
   </div>
 </div>
</template>

<script>
import { ref, reactive } from "vue";
export default {
 setup(props) {
   const data = reactive({
     title: "Vuex",
   });
   return { data };
 },
};
</script>

クリックイベントを追加します。

<div class="btn btn-secondary w-100"
     @click.exact="$store.commit('count', 1)"
     @click.shift="$store.commit('count', 2)"
     @click.alt="$store.commit('count', 3)"
>

何も押さずにクリックすると1を、
shiftを押しながらクリックすると2を、
altを押しながらクリックすると3を、ミューテーションに渡しています。

こんな感じに値を渡します。


■まとめ

今回は、ストアに関してでした。今のところ、複数のコンポーネントで共通の値を保持したいときとかに使うのかな?という認識です。

もうちょっとVuexは続きます。

この記事が気に入ったらサポートをしてみませんか?