为什么状态在 vuex 中没有更新?

时间:2021-07-29 11:33:11

标签: javascript vue.js axios state vuex

我正在使用 vuex 和 axios 从后端获取数据。当我控制台记录状态时,它会显示更新的状态。但是,我调用状态时总是没有数据。有什么我遗漏的吗?

vuex 文件

import axios from "axios"; 
import { uid } from "quasar";

const state = {
  data: {},
};

const mutations = { 
  addData(state, payload) {
    state.data[payload.id] = payload.data;
    console.log(state.data); //the data exist
  },
};



 const actions = {
      readData({ commit }) {
        axios({
          method: "get",
          url:
            "https://dev.activate.vi9e.com/api/purchase/receivegoods/index?action=list",
          headers: {
            "Content-Type": "application/json",
          },
        })
          .then((response) => {
            for (var i = 0; i < response.data.length - 1; i++) {
              let dataId = uid();
              let payload = {
                id: dataId,
                data: response.data[i],
              };
              commit("addData", payload);
            }
          })
          .catch((error) => {
            //handle error
            console.log("error message: ", error.message);
          });
      },
    };

const getters = {
  data: (state) => {
    return state.data;
  },
};

export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters,
};

这是我的模板:

<template>
  <p>{{ data }}</p>
</template>

<script>
import { mapGetters, mapActions } from "vuex";

export default {
  methods: {
    ...mapActions("incominggoods", ["readData"]),
  },
  computed: {
    ...mapGetters("incominggoods", ["data"]),
  },
  mounted() {
    this.readData();
  }

};
</script>

即使我在控制台登录突变时获取数据,状态中的数据也根本没有更新。我该如何解决这个问题?

解决方案 感谢所有的评论。它们都值得解决问题。问题是由于 vue 的反应性。 Vue 貌似不允许处理“对象”(非原始数据类型),也不允许对象通过数组赋值的方式来处理“对象”。这是我根据评论所做的:

  1. 我手动操作了从后端收到的数据(其中具有“对象数据类型”(非原始数据类型)并将其更改为“对象数据类型”)。

在行动中(在那时(响应)内)

for (var i = 0; i < response.data.length; i++) {
          let dataId = uid();

         // manipulate the "object" to "Object"
          let data = {
            poid: response.data[i].purchase_order_id,
            podate: response.data[i].po_date,
            vendor: response.data[i].vendor_name,
            qty: "0%",
            total_qty_ordered: response.data[i].total_qty_ordered,
            total_qty_receivable: response.data[i].total_qty_receivable,
            total_qty_received: response.data[i].total_qty_received,
            status: response.data[i].status,
            barcode: response.data[i].purchase_order_id,
            printed_id: response.data[i].printed_id,
          };
// END OF THE MANIPULATION 

          let payload = {
            id: dataId,
            data: data,
          };
          commit("addData", payload);

突变

addData(state, payload) {
    Vue.set(state.data, payload.id, payload.data);
  },

2 个答案:

答案 0 :(得分:0)

Vue 的反应式系统无法检测对象属性添加,请参阅 Reactivity in Depth

在你的突变中,改变这个

state.data[payload.id] = payload.data;

为此:

Vue.set(state.data, payload.id, payload.data);

答案 1 :(得分:0)

对于非原始类型(对象和数组,进一步阅读的对象),JS 反应性有点奇怪。 把一个物体想象成一辆带有彩色窗户的公共汽车。如果一个乘客(数组中的项目或对象中的键/值)或乘客进出公交车,而您从街上看着它,您将不知道发生了什么变化,公交车仍然看起来像相同的。这基本上就是它的工作原理,并且您有 2 个对象反应性选项。

您可以:

a) 替换整个对象

b) 在 Vue 的情况下,使用 Vue.set(用于实际对象,而不是用于数组)

选项 a) 如下所示:

// for objects
const addObjectProperty = (state, property) => {
  state.object = {...state.object, property)
}
// for arrays
const addArrayItem = (state, item) => {
  state.array = [...state.array, item]
}

这样做是使用对象字面量语法({} 或 [ ])动态创建一个新对象。所以这样,Vue 正在查看您的 state.object,并看到它被一个全新的替换并做出相应的反应。

选项 b) 看起来像这样:

const addObjectProperty = (state, property) => {
  // Vue.set params: object, key, value 
  Vue.set(state.object, state.object[property], property)
}

对于数组,只需使用数组方法,不要手动更改 arr[x] = 10 之类的值,因为那样会导致同样的问题。

编辑: 如果你有嵌套对象作为状态属性,你仍然需要替换顶级对象。

state: {
  this: {},
  is: {},
  what: {},
  you: {},
  need: {},
  to: {},
  change: {},
  not: {
    this: {}
  }
}
}

如果您有很多嵌套状态,最简单的方法是使用 vuex modules