【问题标题】:VueJs + Vuex + mapActionsVueJs + Vuex + mapActions
【发布时间】:2018-08-23 03:35:45
【问题描述】:

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

我在我的组件中使用 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 等同于 this.$store.dispatch。

  • 为什么我没有收到消息?
  • 还有其他解决方案吗?

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

PS2:我使用商店中的模块

谢谢

【问题讨论】:

  • 它适用于我(控制台日志打印):jsfiddle.net/acdcjunior/s7k3fxsn
  • 我写了一小段代码,所以执行起来很快,但是如果你添加一个 setTimeout 来模拟一个大的操作,就会有问题。
  • 我认为问题可能在于处理承诺,然后......看看jsfiddle.net/acdcjunior/s7k3fxsn/16看看它是否更清楚
  • 好的,这意味着即使 mapAction / dispatch 返回了一个承诺,在我的情况下,我有义务添加一个等待“突变”结束的承诺。我从文档中认为它是通过 mapAction 精确管理的。准确吗?
  • 我试图在答案中解决这个问题。请检查一下。

标签: vuejs2 vuex


【解决方案1】:

每个 Vuex 动作都会返回一个Promise

Vuex wraps the results of the action functions into Promises。所以changeColor 中的操作:

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

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

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

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

.dispatch('changeColor', ...) Vuex 将返回Promise.resolve(undefined)

如果您希望操作返回的 Promise 等待,您应该返回一个 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>

更新/每 cmets:

即使 mapAction/dispatch 返回一个 promise,在我的情况下,我也有义务添加一个 promise 以等待“突变”的结束。我认为,从文档中,它是通过 mapAction 精确管理的。准确吗?

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

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

那么返回的Promise 只会在commit() 完成后执行

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

之所以会这样,是因为无需等待。这是因为 Vuex 需要:mutations must be synchronous operations

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

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

【讨论】:

  • 如果我调用“mapGetters”并且返回数据需要时间,就会出现问题。假设我通过调用调用“mapGetters / getall”的“getAll”方法来循环使用“v-for”。 DOM 中绝对没有发生任何事情
  • 当然。在我的模板中:&lt;div v-for="a in M"...&gt;&lt;/div&gt;. 在我的方法中,M() { return ...mapGetters("getAll(data)") }。在存储中,getter:{ getAll:state... }`
  • 没有 mapGetters 是可以的(只是示例)。问题是:如果 getter 花费大量时间(正如我们在 setTimeout 中看到的那样),则 dom 不会使用数据渲染
  • 我们可以这么说。渲染之前需要很长时间(我的状态下有很多数据)。所以它是一个异步的
  • 是的,我知道。所以我有义务调用一个mapAction,如果我需要很长时间,它会从状态而不是mapGetter返回给我的值?
猜你喜欢
  • 2020-07-24
  • 2020-10-22
  • 1970-01-01
  • 2019-04-18
  • 2020-11-22
  • 2020-09-27
  • 2018-06-03
  • 2019-02-13
  • 2018-04-17
相关资源
最近更新 更多