0

我已经在这里和其他地方阅读了多个类似的问题,但我无法弄清楚。

我有一个表单,其中mapGetters包含应该根据 Vuex 状态更新的输入值:

    ...mapGetters({
      show: "getShow"
    }),

示例表单输入(我正在使用 Bootstrap Vue):

      <b-form-input
        id="runtime"
        name="runtime"
        type="text"
        size="sm"
        v-model="show.runtime"
        placeholder="Runtime"
      ></b-form-input>

然后我在表单组件上有这个方法:

    async searchOnDB() {
      var showId = this.show.showId;
      if (!showId) {
        alert("Please enter a showId");
        return;
      }
      try {
        await this.$store.dispatch("searchShowOnDB", showId);
      } catch (ex) {
        console.log(ex);
        alert("error searching on DB");
      }
    },

以及对商店的此操作:

    async searchShowOnDB({ commit, rootState }, showId) {
      var response = await SearchAPI.searchShowOnDB(showId);
      var show = {
        show_start: response.data.data.first_aired,
        runtime: response.data.data.runtime,
        description: response.data.data.overview
      };
      //I'm updating the object since it could already contain something
      var new_show = Object.assign(rootState.shows.show, show);
      commit("setShow", new_show);
    }

突变:

    setShow(state, show) {
      Vue.set(state, "show", show);
    }

搜索API:

export default {
    searchShowOnDB: function (showId) {
        return axios.get('/search/?id=' + showId);
    },
}

一切正常,API 调用被执行,我什至可以在 Vue Devtools 中看到 Vuex 更新状态,但表单没有更新。只要我在输入字段中写入内容或在 Vue Devtools 中点击,commit表单字段show_start,都会更新。runtimedescription

此外,这可以正常工作并更新所有内容:

    async searchShowOnDB({ commit, rootState }, showId) {
      var show = {
        show_start: "2010-03-12",
        runtime: 60,
        description: "something"
      };
      //I'm updating the object since it could already contain something
      var new_show = Object.assign(rootState.shows.show, show);
      commit("setShow", new_show);
    }

我不知道还能做什么,我尝试通过明确解决 Promises,删除 async/await 和 use axios.get(...).then(...),移动东西......似乎没有任何效果。

4

2 回答 2

1

15/modules/search.js使用Object.assign()的线上rootState.search.show。这会改变的searchprop state(这是错误的,顺便说一句,你应该只在突变内部进行突变!)。阅读下面的原因。

然后你试图触发突变。但猜猜怎么了?Vue 看到它是相同的值,所以没有通知组件,因为没有变化。这就是为什么你不应该突变之外进行突变!

因此,不要将值分配给您的操作中的状态,只需提交新的显示(将行替换15-16为:

 commit('setShow', show);

在这里查看:https ://codesandbox.io/s/sharp-hooks-kplp7?file=/src/modules/search.js

这将完全替换state.showshow. 如果您只想将响应合并到 currentstate.show中(以保留您添加到 current 的一些自定义内容show),您可以传播以下内容state.show并用以下内容覆盖show

commit("setShow", { ...rootState.search.show, ...show });

另请注意,您不需要Vue.set()突变。你有state任何突变的第一个参数,这state是当前模块的。所以只需分配state.show = show.

最后一点:当你的 vuex 变得更大时,你可能想要命名你的模块,以避免任何名称冲突。

于 2020-04-29T16:43:42.583 回答
0

模板中使用的处于状态的对象的所有道具都必须存在,或者您应该为此类属性调用 Vue.set。

  state: {
    show: {
      runtime: null // <- add this line
    }
  },

您为整个对象调用 Vue.set 但它已经存在于状态中,并且您不会用新对象替换它,您只需替换道具。在您的情况下,您有一个空对象并使用 Object.assign 添加“运行时”支持它。此外,所有状态操作都应在突变中完成:

      var new_show = {
        runtime: response.data.url
      };
      commit("setShow", new_show);
...
  mutations: {
    setShow(state, new_show) {
      Object.assign(state.show, new_show)
    }
  },


于 2020-04-29T15:44:13.213 回答