VueJs + Vuex + mapActions

VueJs + Vuex + mapActions

在文档中写道,除了通过操作调用的突变之外,状态是不可变的……好的。

我在我的组件中使用 mapGetters、mapActions ...

商店:

export default {
  namespaced: true,

  state: {
    color: "violet"
  },
  mutations: {
      changeColor(state, newColor) {
          state.color = newColor
      },
  },
  actions: {
    changeColor({ commit }, newColor) {
      commit('changeColor', newColor)
  }
 }

组件:

...
methods: {
    ...mapActions({
      setColor: 'store/changeColor',
    }),
    myMethodCallByButton(){
       this.setColor("blue").then(response => {
          console.log("change Color done")
       },err => {
          console.log("change Color error")
       })
    }
...

该方法工作正常,商店已更新,除了我从未收到 console.log ()。

文档中写到mapActions相当于这个。$store.dispatch.

PS:我想保留 mapGetters 地图,mapActions ..我不喜欢调用它。$store.dispatch

PS2:我在商店中使用模块

谢谢

每个 Vuex action returns a Promise.

Vuexwraps the results of the action functions into Promises。所以 changeColor 动作在:

actions: {
  changeColor({ commit }, newColor) {
    myAsyncCommand();
  }
}

Returns 解析为 undefinedPromise 并且 不会等待 完成 myAsyncCommand(); 的异步代码(如果它不包含异步代码,则无需等待)。

发生这种情况是因为上面的代码与以下代码相同:

  changeColor({ commit }, newColor) {
    myAsyncCommand();
    return undefined;
  }

而当 .dispatch('changeColor', ...) Vuex 将 return Promise.resolve(undefined).

如果您希望 Promise return 由操作编辑的等待,您应该 return 一个 Promise 来执行您自己等待的属性。大致如下:

  changeColor({ commit }, newColor) {
    return new Promise((resolve, reject) => {
      myAsyncCommand().then(resolve);
    });
    // or, simply: return myAsyncCommand();
  }

下面的演示实现有更多细节:

const myStore = {
  namespaced: true,
  state: { color: "violet" },
  mutations: {
      changeColor(state, newColor) {
          state.color = newColor
      }
  },
  actions: {
    changeColor_SIMPLE({ commit }, newColor) {
      commit('changeColor', newColor)
    },
    changeColor_COMPLICATED_NO_PROMISE({ commit }, newColor) {
        setTimeout(() => {
          commit('changeColor', newColor)
        }, 2000)
    },
    changeColor_COMPLICATED_WITH_PROMISE({ commit }, newColor) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          commit('changeColor', newColor)
          resolve();
        }, 2000)
      });
    }
  }
};
const store = new Vuex.Store({
  modules: {
    store: myStore,
  }
});
new Vue({
  store,
  el: '#app',
  methods: {
    ...Vuex.mapActions({
      setColorSimple: 'store/changeColor_SIMPLE',
      setColorComplicatedNoPromise: 'store/changeColor_COMPLICATED_NO_PROMISE',
      setColorComplicatedWithPromise: 'store/changeColor_COMPLICATED_WITH_PROMISE',
    }),
    myMethodCallByButton(){
       this.setColorSimple("blue")
        .then(response => console.log("SIMPLE done"),err => console.log("SIMPLE err"));
      this.setColorComplicatedNoPromise("blue")
        .then(response => console.log("NO_PROMISE done"),err => console.log("NO_PROMISE err"));
      this.setColorComplicatedWithPromise("blue")
        .then(response => console.log("WITH_PROMISE done"),err => console.log("WITH_PROMISE err"));
    }
  }
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.min.js"></script>
<script src="https://unpkg.com/vuex"></script>

<div id="app">
  <p>color: {{ $store.state.store.color }}</p>
  <button @click="myMethodCallByButton">click me and WAIT for 2s</button>
</div>

Update/Per 评论:

Even if the mapAction / dispatch returns a promised, I am in my case obliged to add a promise to wait for the end of the "mutation". I thought, from the documentation, that it was precisely managed via the mapAction. Is it exact?

如果一个动作只调用一个突变,例如:

actions: {
  changeColor({ commit }, newColor) {
    commit('changeColor', newColor)
    return undefined; // added for clarity
  }
}

然后 returned Promise 将仅在 commit() 完成后执行

这不会发生,因为 Vuex 管理等待突变(commits)。

事情就是这样发生的,因为没有等待。这是因为 Vuex 要求:mutations must be synchronous operations.

由于突变是同步的,上面的return行只会在(commit('changeColor', newColor))之前的行代码之后执行。

注意:如果你的 mutations 有异步代码,你应该让它们同步,因为它违背了 Vuex 的正常工作方式并且可能会产生各种意外行为。