【问题标题】:Vuex store only keeps one component updated, not bothVuex store 只更新一个组件,而不是两个
【发布时间】:2018-05-11 16:10:17
【问题描述】:

所以我有一个带有一些变量的 Vuex 存储,它看起来像这样:

var dataStore = new Vuex.Store({
    state: {
        consumer_id: undefined,
        some_other_data: 0
    },
    mutations: {
        update: function(type, payload) {
            state = Object.assign(type, payload);
        }
    }
});

我有两个组件,它们都是顶级的 Vue 组件。但是MultiSim 包围Sim。他们都使用以下方法访问consumer_id

consumer_id: {
    get: function () {
        return this.$store.state.consumer_id;
    },
    set: function (value) {
        this.$store.commit('update', {consumer_id: value});
    }
},

问题在于,虽然对consumer_id 的更改会传播到Sim,但MultiSim 只会看到undefined(默认值)。 MultiSim 更改 consumer_id,这被所有三个组件正确捕获,但如果 Sim 更改,MultiSim 不会更新。

例如:

  • MultiSim 设置consumer_id = 10
  • [MultiSim: 10, Sim: 10, Store: 10]
  • Sim 设置consumer_id = 5
  • [MultiSim: 10, Sim: 5, Store: 5]

谁能看出我哪里出错了?有没有办法强制更新所有组件?

编辑:

所以我找到了一个解决方案,但它更像是一种 hack:

  • MultiSim 设置consumer_id = 10
  • [MultiSim: 10, Sim: 10, Store: 10]
  • Sim 设置consumer_id = 5
  • `[MultiSim: this.$store.state.consumer_id /* 5 */, Sim: 5, Store: 5]

本质上,MultiSim 的计算方法并没有更新,即使它可以正常访问实际存储的值。

【问题讨论】:

  • 你的变异看起来不对。 state 看起来不像它会被定义(在你的情况下,状态是type)。此外,如果没有replaceState IIRC,您将无法替换整个状态。
  • 我尝试过使用Vue.set(profitSimulatorStore.$store.state, k, payload[k]);,但遇到了未定义的错误。你有Vue.set 语法的例子吗?

标签: vue.js vuex


【解决方案1】:

假设您的所有状态属性在您创建商店时都已初始化,您可以使用以下方法将通用有效负载发送到您的更新突变:

const store = new Vuex.Store({
  state: {
    consumer_id: undefined,
    some_other_data: 0
  },
  mutations: {
    update: function(state, payload) {
      for ([key, value] of Object.entries(payload))
        state[key] = value
    }
  }
})

这将允许您的 update 突变是通用的并设置状态属性。

这是一个例子。

console.clear()

const store = new Vuex.Store({
  state: {
    consumer_id: undefined,
    some_other_data: 0
  },
  mutations: {
    update: function(state, payload) {
      for ([key, value] of Object.entries(payload))
        state[key] = value
    }
  }
})

const Sim = {
  template: `
<div>
Sim <input v-model="consumer_id"> {{consumer_id}}
</div>
`,
  computed:{
    consumer_id: {
      get: function () {
        return this.$store.state.consumer_id;
      },
      set: function (value) {
        this.$store.commit('update', {consumer_id: value});
      }
    },    
  }
}

const MultiSim = {
  template: `
    <div>
      MultiSim <input v-model="consumer_id"> {{consumer_id}}
    </div>
    `,
  computed:{
    consumer_id: {
      get: function () {
        return this.$store.state.consumer_id;
      },
      set: function (value) {
        this.$store.commit('update', {consumer_id: value});
      }
    },    
  }
}

new Vue({
  el: "#app",
  store,
  components: {Sim, MultiSim}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  <sim></sim>
  <multi-sim></multi-sim>
</div>

如果属性没有在商店创建时的状态上初始化,那么你将需要使用 Vue.set。

const store = new Vuex.Store({
  state: {
  },
  mutations: {
    update: function(state, payload) {
      for ([key, value] of Object.entries(payload))
        Vue.set(state, key, value)
    }
  }
})

此外,这两者都假定您在每种情况下都在创建有效负载,就像您在计算集中所做的那样。

注意:IE 不支持 Object.entries,因此您可能需要使用 Object.keys。

【讨论】:

  • 恐怕这两种方法的结果都与我原来的方法相同。
  • @Darkstarone 需要更多代码来复制。它适用于上面的示例。
  • 是的,我会试着做一个失败的小例子——代码本身有几千行,所以让你尝试调试它没有意义!感谢您迄今为止的帮助。
  • @Darkstarone 听起来不错;当你把东西放在一起时给我打电话;我对解决方案感兴趣。
  • 我找到了部分解决方案(见编辑),我可以通过this.$store.state.consumer_id 访问consumer_id 以获取正确的值,但计算的方法无法正常工作。恐怕无法用一个小示例进行复制,玩具示例都可以正常工作(就像实时代码中的所有其他组件一样!)
猜你喜欢
  • 1970-01-01
  • 2021-12-25
  • 2019-08-02
  • 1970-01-01
  • 2019-02-18
  • 2020-06-24
  • 1970-01-01
  • 2018-10-09
  • 1970-01-01
相关资源
最近更新 更多