web-dev-qa-db-ja.com

Vuexのゲッターからディスパッチできますか

フィドル: ここ

Vue 2を使用してwebappを作成しています。ゲッターから状態データをフェッチするストアがあります。ゲッターがデータがまだ入力されていないことがわかった場合に必要なのは、ディスパッチを呼び出し、データをフェッチします。

以下は私のVuexストアです。

const state = {
  pets: []
};

const mutations = {
  SET_PETS (state, response) {
    state.pets = response;
  }
};

const actions = {
 FETCH_PETS: (state) => {
      setTimeout(function() { 
            state.commit('SET_PETS', ['t7m12qbvb/Apple_9', '6pat9znxz/1448127928_kiwi'])
    }, 1000)
 }
}

const getters = {
    pets(state){
    if(!state.pets.length){
        state.dispatch("FETCH_PETS")
    }
    return state.pets
  }
}

const store = new Vuex.Store({
  state,
  mutations,
  actions,
  getters
});

しかし、私は次のエラーを得ています:

Uncaught TypeError:state.dispatch is not a function(…)

VueコンポーネントのbeforeMountからこれを実行できることはわかっていますが、同じVuexストアを使用する複数のコンポーネントがあるため、いずれかのコンポーネントで実行する必要があります。どちらにするべきか、それが他のコンポーネントにどのように影響するか。

17
Saurabh

ゲッターは、ストアのstateではなくcontextを渡されているため、ディスパッチを呼び出すことができません。

アクションは、コンテキストが渡されるときに、状態、ディスパッチ、コミットを呼び出すことができます。

ゲッターは「派生状態」を管理するために使用されます。

代わりに、それを必要とするコンポーネントにpets状態を設定する場合は、アプリのルートからFETCH_PETSを呼び出し、ゲッターの必要性を削除するだけです。

8
GuyC

同じ問題がありました。また、すべてのVueインスタンスが自動的に何かをロードすることを望み、ミックスインを作成しました。

store.registerModule('session', {
    namespaced: true,
    state: {
        session: {hasPermission:{}},
        sessionLoaded:false
    },
    mutations: {
        changeSession: function (state, value)
        {
            state.session = value;
        },
        changeSessionLoaded: function (state)
        {
            state.sessionLoaded = true;
        }

    },
    actions: {
        loadSession(context)
        {
            // your Ajax-request, that will set context.state.session=something
        }
    }
}); 

Vue.mixin({
    computed: {
        $session: function () { return this.$store.state.session.session; },
    },
    mounted:function()
    {
        if(this.$parent==undefined && !this.$store.state.session.sessionLoaded)
        {
            this.$store.dispatch("session/loadSession");
            this.$store.commit("changeSessionLoaded");
        }
    },
});

vue-instanceごとに1つだけをロードして格納し、すべてのvue-instanceに自動的に含まれるため、すべてのメインアプリで定義する必要はありません。

0
mech