hysryt / wiki

https://hysryt.github.io/wiki/
0 stars 0 forks source link

Vuex #34

Open hysryt opened 6 years ago

hysryt commented 6 years ago

ストアの作成

ストアは複数のステート、ゲッターを持つ ステートとデータはほぼ同義

import Vuex from 'vuex'

const store = new Vuex.Store({
  state: {
    count: 0
  }
})

ルートコンポーネントにストアを登録

ルートコンポーネントに登録したストアは全ての子コンポーネントに注入される

import Vue from 'vue'

Vue.use(Vuex);

new Vue({
  el: '#app',
  store: store,
  components: {
    ChildComponent
  }
})

子コンポーネントからのアクセス

const ChildComponent = {
  computed: {
    count() {
      return this.$store.state.count    // this.$storeでストアにアクセス
    }
  }
}
hysryt commented 6 years ago

mapState

子コンポーネントからアクセスする際の算出プロパティ用のヘルパー関数

// mapStateなし
const ChildComponent = {
  computed: {
    count() {
      return this.$store.state.count
    }
  }
}
// mapStateあり
import { mapState } from 'vuex'

const ChildComponent = {
  computed: mapState({
    count: state => state.count
  })
}
// または
import { mapState } from 'vuex'

const ChildComponent = {
  computed: mapState([
    'count'
  ])
}

引数でthis.$store.stateを取得できるので記述量が減り、さらにthisが必要ないのでアロー関数で書ける

hysryt commented 6 years ago

ゲッター

ストアは複数のゲッターを持つことができる ゲッターは、ステートの値をフィルタリングや加工したい場合などに使用する Vue.jsでの算出プロパティに近い

ストアにフィルタリングまたは加工処理を登録することで、複数のコンポーネントで処理を共有できる

import Vuex from 'vuex'

const store = new Vuex.Store({
  state: {
    count: 0
  },

  getters: {
    nextCount: state => {
      return state.count + 1
    }
  }
})

子コンポーネントからのアクセス

const ChildComponent = {
  computed: {
    nextCount() {
      return this.$store.getters.nextCount
    }
  }
}

ゲッターの返り値は関数にすることもできる

hysryt commented 6 years ago

mapGetters

子コンポーネントからゲッターにアクセスする際のヘルパー関数

// mapGettersなし
const ChildComponent = {
  computed: {
    nextCount() {
      return this.$store.getters.nextCount
    }
  }
}
// mapGettersあり
import { mapGetters } from 'vuex'

const ChildComponent = {
  computed: mapGetters([
    'nextCount'
  ])
}
hysryt commented 6 years ago

ミューテーション

ストアは複数のミューテーションを持つことができる ミューテーションはステートの値を変更するイベント ステートの値の変更はミューテーションを介してのみ行われる

import Vuex from 'vuex'

const store = new Vuex.Store({
  state: {
    count: 0
  },

  getters: {
    nextCount: state => {
      return state.count + 1
    }
  },

  mutations: {
    increment: state => {
      state.count += 1
    }
  }
})

子コンポーネントからミューテーションの実行

ミューテーション名を引数にcommit()することでミューテーションを実行できる

const ChildComponent = {
  methods: {
    increment: function() {
      this.$store.commit('increment')
    }
  }
}

commit()は第二引数でペイロードを渡すことができる

const ChildComponent = {
  methods: {
    increment: function() {
      this.$store.commit('increment', {
        num: 10
      })
    }
  }
}

ミューテーション側は第二引数でペイロードを受け取ることができる

mutations: {
  increment: (state, payload) => {
    state.count += payload.num;
  }
}
hysryt commented 6 years ago

mapMutations

ミューテーション実行関数のヘルパー関数

// mapMutationsなし
const ChildComponent = {
  methods: {
    increment: function() {
      this.$store.commit('increment')
    }
  }
}
// mapMutationsあり
import { mapMutations } from 'vuex'

const ChildComponent = {
  methods: mapMutations([
    'increment'
  ])
}
hysryt commented 6 years ago

アクション

ストアは複数のアクションを持つことができる アクションはミューテーションをコミットする ミューテーションは即座に(同期的に)処理をする必要があるのに対し、 アクションは非同期処理を含むことができる

import Vuex from 'vuex'

const store = new Vuex.Store({
  state: {
    count: 0
  },

  getters: {
    nextCount: state => {
      return state.count + 1
    }
  },

  mutations: {
    increment: state => {
      state.count += 1
    }
  },

  actions: {
    increment: context => {
      setTimeout(() => {
        context.commit('increment');
      }, 1000)
    }
  }
})

アクションが実行されてから1秒後にミューテーションを実行している

子コンポーネントからアクションを実行する

アクション名を引数にdispatch()することでアクションを実行できる

const ChildComponent = {
  methods: {
    increment: function() {
      this.$store.dispatch('increment')
    }
  }
}

ミューテーションと同じように、dispatch()は第二引数でペイロードを渡すことができる

const ChildComponent = {
  methods: {
    increment: function() {
      this.$store.dispatch('increment', {
        num: 10
      })
    }
  }
}

アクション側は第二引数でペイロードを受け取ることができる

actions: {
  increment: (context, payload) => {
    setTimeout(() => {
      console.log(payload.num);
      context.commit('increment');
    }, 1000)
  }
}

hysryt commented 6 years ago

mapActions

アクション実行関数用のヘルパー関数

// mapActionsなし
const ChildComponent = {
  methods: {
    increment: function() {
      this.$store.dispatch('increment')
    }
  }
}
// mapActionsあり
import { mapActions } from 'vuex'

const ChildComponent = {
  methods: mapActions([
    'increment'
  ])
}
hysryt commented 6 years ago

モジュール

ストアはモジュールという単位で分割できる。 モジュールは、ステート、ゲッター、ミューテーション、アクション、モジュールを内包できる。

// モジュールA - ステートとミューテーションを持つ
const moduleA = {
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  }
}

// ストア - モジュールAを持つ
const store = new Vuex.Store({
  modules: {
    a: moduleA
  }
});

子コンポーネントからモジュールへのアクセス

ステートとゲッター、ミューテーション、アクションでアクセス方法が異なる。 ゲッター、ミューテーション、アクションはどのモジュールで定義されたとしても、全て同じ名前空間に配置される。

ステートへのアクセス

$store.state.モジュール名.ステート名 モジュールがさらにモジュールを内包している場合は$store.state.モジュール名.モジュール名.ステート名となる。 つまりモジュールごとに名前空間を持つことになる。

const ChildComponent = {
  computed: {
    count() {
      return this.$store.state.a.count
    }
  }
}

ステート以外へのアクセス

ゲッター、ミューテーション、アクションへのアクセス。 全て同じ名前空間に配置されるため、 ストア直下のミューテーションと同じように呼び出すことができる。 同じ名前のミューテーションが複数ある場合、実行時に全て実行される

const ChildComponent = {
  created() {
    this.$store.commit('increment')
  }
}
hysryt commented 6 years ago

名前空間付きモジュール

ゲッター、ミューテーション、アクションは名前空間内に配置することもできる namespaced:trueを追加する

const moduleA = {
  namespaced: true,
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  }
}

呼び出す場合は名前空間付きでa/incrementのように指定する

export default {
  created() {
    this.$store.commit('a/increment')
  }
}
hysryt commented 6 years ago

Vuexの原理原則

https://vuex.vuejs.org/ja/structure.html

例:https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart

hysryt commented 6 years ago

v-modelの代用

Vuexではv-modelでの双方向バイディングは許されていない :value@inputまたはgetsetで代用する必要がある https://vuex.vuejs.org/ja/forms.html

hysryt commented 6 years ago

Vuexのメリット