为什么状态更新后数据会改变?

时间:2020-08-10 06:13:09

标签: javascript vuejs2 vuex

我在vuex中使用vue,而我只花了几个小时来查找问题。也许你可以帮忙。

我的问题是,为什么我使用 CreateTeam.vue 中的newTeam方法创建新团队,而又使用 Team.vue 中的listOfTeams >也已更新?

  • 我从未在 Team.vue 中进行订阅,观看或任何观看者。为什么添加新团队后listOfTeams会更新?
  • 这是vuex的确切行为吗?请赐教。

这是我的 Team.vue

data() {
    return { listOfTeams: [] }
},

methods: {
    loadRecord: async function() {
        const response = await this.$store.dispatch("teams/load");
        this.$store.commit("teams/intitialize", response.data);
        this.listOfTeams = response.data;
    }
},

CreateTeam.vue

methods: {
    newTeam: async function() {
        const response = await this.$store.dispatch("team/store", formData);
        this.$store.commit("teams/add", response.data);
    }
}

这里是我正在使用的 teams.js(模块)

const state = { record: {}, };
const actions = {
    store({commit,state}, payload) { return httpFile().post('/teams', payload); },
    
    load({ commit, state }, payload = "") { return http().get("teams" + payload); }
};

const mutations = {
    intitialize(state, payload) { state.record = payload.data.data; },
    
    add(state, payload) { state.record.unshift(payload.data); },
};

3 个答案:

答案 0 :(得分:2)

JavaScript是一种基于参考的语言(最简单的思考方式是所有变量和成员都是指针)。

这意味着例如

let x = [];
let a = {y: x}; // Doesn't make a copy of x
console.log(a.y.length); // output is 0
x.push(10);
console.log(a.y.length); // output is 1

a.y在创建后为空,但是该成员仍指向与x相同的数组,因此向x添加元素也会向a.y添加元素,因为它们都是指向同一对象的指针。

在您的代码中

this.listOfTeams = response.data;

不会复制response.data,因此,如果该对象被修改(例如,将其清空,并向其添加新值而不是创建新的新鲜数组),那么您的成员也会被更改。

要解决此问题,您可以编写:

this.listOfTeams = response.data.slice();

这样,您的成员类将拥有自己的数组,并且将不会依赖分配给response.data的其他代码。

答案 1 :(得分:1)

这是一个JavaScript对象参考问题。

  1. 您从某个异步HTTP调用中获得了响应,该响应存储在response变量(一个对象)中

  2. 您通过data变异将该对象(以及它的intitialize属性)提交到商店中

    state.record = payload.data.data
    

    在这里,payload.dataresponse.data是同一对象

  3. 然后将您的团队列表data设置为同一对象

    this.listOfTeams = response.data
    

在任何时候您都不会破坏对象引用,因此当您下次添加带有add突变的新团队时,它将直接使用Array.prototype.unshift()来操纵商店数据...

state.record.unshift(payload.data)

您要更改response.data.datathis.listOfTeamsstate.record的全部三个,因为它们都是相同的对象引用。

这就是为什么在进行直接分配时最好将您的商店状态视为不可变以及中断对象引用

const mutations = {
  intitialize (state, { data }) {
    state.record = {...data.data} // break reference via spread
  },
  add(state, { data }) {
    state.record = [data, ...state.record] // immutable
  }
}

答案 2 :(得分:0)

如果您正在或将要使用lodash,则可以尝试使用_.cloneDeep中断引用并根据上一个引用创建新值