サイトアイコン 上尾市のWEBプログラマーによるブログ

「これからはじめるVue.js実践入門」の感想・備忘録7

「これからはじめるVue.js実践入門」の感想・備忘録6の続き

Vuex

Vuexの準備

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

Vuexを使ったカウンターのサンプル

1. src/store/index.jsのstateにデータ本体を定義し、mutationsにステートを操作するためのメソッドを定義する。

export default new Vuex.Store({
  // struct: true,
  state: {
    count: 0
  },
  mutations: {
    minus(state) {
      state.count--;
    },
    plus(state) {
      state.count++;
    }
  },
})

2. ストアをアプリに登録する。

import store from './store'
〜省略〜
new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

3. コンポーネントからストアを呼び出す。

<template>
  <div id="app">
    <h1>{{ count }}</h1>
    <button @click="plus">+</button>
    <button @click="minus">-</button>
  </div>
</template>
<script>
export default {
  name: 'App',
  computed: {
    count() {
      return this.$store.state.count;
    }
  },
  methods: {
    plus() {
      this.$store.commit('plus');
    },
    minus() {
      this.$store.commit('minus');
    }
  }
}
</script>

mapStateヘルパー関数

import { mapState } from 'vuex'
//として以下のようにステートのプロパティ名を指定するだけ。
computed: mapState(['count']),

//他の算出プロパティとまとめる場合はスプレッド演算子を使う。
computed: {
  hoge() {
    return this.name;
  },
  ...mapState(['count']),
}
computed: {
  count() {
    return this.$store.state.count;
  }
},
// 上記の記述を以下のように省略して記述できるようなる。
computed: mapState(['count']),

// ステートと違う名前の算出プロパティにしたい場合はオブジェクトにする。
computed: mapState( { countNum: 'count' } ),

Vuexを構成する要素

ゲッター(getters)

// ストアで定義
getters: {
  tenTimes(state) {
    return state.count * 10;
  }
}
// コンポーネントでmapGettersを使って算出プロパティにマージする。
import { mapGetters } from 'vuex'
// 〜省略〜
computed: {
  ...mapGetters(['tenTimes']),
},
ゲッターで他のゲッターを使う場合
getters: {
  tenTimes(state) {
    return state.count * 10;
  },
  twentyTimes(state, getters) {
    return getters.tenTimes * 2;
  },
}
引数を受け取る場合
getters: {
  multiply(state) {
    return num => {
      return state.count * num;
    }
  },
}
computed: {
  ...mapGetters(['multiply']),
},
// は以下と同じ意味になる。
methods: {
  multiply(num) {
    return this.$store.getters.multiply(num);
  }
}
// よって、mapGettersを使うとcomputedではなくmethodsとなるためキャッシュされない。
// キャッシュさせたい場合は、mapGettersを使わずに算出プロパティとして定義する必要がある。
computed: {
  multiply() {
    return this.$store.getters.multiply(this.num);
  }
},

ミューテーション(mutations)

mutations: {
  plusX(state, payload) {
    state.count += payload.num;
  }
},
methods: {
  plusX() {
    this.$store.commit('plusX', {num: 2});
  },
},
mapMutationsヘルパー関数
methods: {
  plus() {
    this.$store.commit('plus');
  },
  minus() {
    this.$store.commit('minus');
  }
}
// は以下のように書くことができる。
import { mapMutations } from 'vuex'
// 〜省略〜
methods: {
  ...mapMutations(['plus', 'minus']),
}
ステートに対しての双方向バインディング
<input type="text" v-model="originCount">
// 〜省略〜
computed: {
  originCount: {
    get() {
      return this.$store.state.count;
    },
    set(value) {
      return this.$store.commit('setCount', {count: value});
    }
  }
},

アクション(actions)

actions: {
  setCountAsync(context, payload) {
    setTimeout(() => {
      context.commit('setCount', payload);
    }, 2000);
  }
}
methods: {
  setCountAsync() {
    this.$store.dispatch('setCountAsync', {count: 10});
  },
},
mapActionsヘルパー関数
import { mapActions } from 'vuex'
// 〜省略〜
methods: {
  ...mapActions(['plusAsync']),
},

モジュール

export default new Vuex.Store({
  modules: {
    module1: Module1,
    module2: Module2
  }
})
export default{
  namespaced: true,
  state: {
    count: 0
  },
  mutations: {
    plus(state) {
      state.count++;
    }
  },
}
<template>
  <div>
  <p>{{ count1 }}</p>
  <p>{{ count2 }}</p>
  <button @click="plusForModule1">+</button>
  <button @click="plusForModule2">+</button>
  </div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'App',
  computed: {
    count1() {
      return this.$store.state.module1.count;
    },
    ...mapState({
      count2: state => state.module2.count
    })
  },
  methods: {
    plusForModule1() {
      this.$store.commit('module1/plus');
    },
    ...mapMutations({
      plusForModule2: 'module2/plus'
    })
  }
}
</script>
モバイルバージョンを終了