vuex无法跟踪Object新增的属性。

Created on 29 Jun 2016  ·  6Comments  ·  Source: vuejs/vuex

代码

// store.js
import Vue from 'vue';
import Vuex from 'vuex';


Vue.use(Vuex);


const state = {
  count: {},
};

const mutations = {
  /* eslint no-shadow: "off" */
  INCREMENT(state, amount) {
    /* eslint no-param-reassign: "off" */
    if (!state.count.count) {
      state.count.count = 0;
    }
    state.count.count = state.count.count + amount;
  },
};

export default new Vuex.Store({
  state,
  mutations,
});

// getter.js
export const getCount = state => state.count.count;

// actions.js
export const incrementCounter = ({ dispatch }) => dispatch('INCREMENT', 1);

在调用incrementCounter后,会在vue.$store.state.count初始值为{},中添加对象{count:1},vue.$store.state.count变为{count:1}。
这个变化在vuedevtools中能跟踪到,但在绑定了‘getCount’的vue对象中,相应的值却无法得到更新。

// 显示组件的代码

<template>
  <div>
    count is {{ counterVaule }}
  </div>
</template>

<script>
  import { getCount } from '../vuex/getters.js';
  export default {
    vuex: {
      getters: {
        counterVaule: getCount,
      },
    },
  };
</script>

<style scoped>
div {
  color: rgb(72, 214, 154);
}
</style>

counterVaule会一直为undefined。
untitled

在一个对象上添加新的属性后,显示组件中的值不会自动更新。
代码:https://github.com/forclan/vue-error-objinit/tree/master/src
演示实例:http://forclan.github.io/Vue/vue-error/

Most helpful comment

You can use Vue.set.

const mutations = {
  INCREMENT(state, amount) {
    if (!state.count.count) {
      Vue.set(state.count, 'count', 0);
    }
    state.count.count = state.count.count + amount;
  },
};

Or set initial state to something like null.

const state = {
  count: { count: null },
};

This is a restriction of Vue's reactive system. You have to use Vue.set when you dynamically add some properties to Object.
I'm sorry if I'm misunderstanding you. (I'm using translation tool)

All 6 comments

if (!state.count.count) {
state.count.count = 0;
}
state.count.count = state.count.count + amount;
state.count = Object.assign({},state.count)

我是想将state.count当做一个hash表来用。
比如说有很多这样的商品对象{id:xxx, orderNum:xxx},想在用户点击时往state.count中添加属性。最后完成时就成为了{ {id:'apple', orderNum:10}, {id:'peach', orderNum:1}};也就是这个id是不确定的,没法在开始的时候进行初始化。

之后采用Array作为存储的结构,虽然麻烦了点,但getters函数能够在数据变化后得到返回值。所以好奇如果直接使用Object对象能不能够类似Array一样,调用某个函数在对Object对象添加属性时,vuex能够追踪到store的变化。

嗯,这样是可以的,就是Vue的设计原理,对于对象的键值改动,建议是用一个全新的对象替换原本的对象

You can use Vue.set.

const mutations = {
  INCREMENT(state, amount) {
    if (!state.count.count) {
      Vue.set(state.count, 'count', 0);
    }
    state.count.count = state.count.count + amount;
  },
};

Or set initial state to something like null.

const state = {
  count: { count: null },
};

This is a restriction of Vue's reactive system. You have to use Vue.set when you dynamically add some properties to Object.
I'm sorry if I'm misunderstanding you. (I'm using translation tool)

thanks a lot, the problem have been solved.

想追踪到数据,必须先进行数据劫持

Was this page helpful?
0 / 5 - 0 ratings