如何在Vuex突变后获得价值?

时间:2018-05-04 13:01:26

标签: javascript vue.js getter-setter vuex vuex-modules

我有一个简单的Vuex模块用于全局日期对象:

import moment from 'moment';

const state = {
    date: moment()
}

// getters
const getters = {
    date: state => state.date,
    daysInMonth: state => state.date.daysInMonth()
}

// mutations
const mutations = {
    subtractOneDay(state) {
        state.date.subtract(1, 'days');
    }
}

export default {
    state,
    getters,
    mutations
}

我的一个子组件:

import { mapGetters, mapMutations } from 'vuex';

export default {
    computed: Object.assign(mapGetters(['date', 'daysInMonth']), {}),
    methods: {
        subtractOneDay() {
            this.$store.commit('subtractOneDay');

            console.log(this.date.format('YYYY-MM-DD'), this.date.daysInMonth(), this.daysInMonth)
        }
    },
    created() {
        console.log('blocks created')
    },
    mounted() {
        console.log('blocks mounted')
    }
}

基本上我需要在date发生变化时获得月中的日期(29,29,30或31)。

问题是计算属性daysInMonth不会改变......

1 个答案:

答案 0 :(得分:2)

Moment的subtract方法会改变引用的时刻对象。对于Vue来说这是一个问题,因为这意味着state.date引用没有改变,计算出的属性也不会重新计算它们的值。

您可以使用片刻clone方法解决此问题,以便在subtractOneDay方法中返回新时刻。

这是一个例子。

console.clear()

const store = new Vuex.Store({
  state:{
    date: moment()
  },
  getters:{
    date: state => state.date,
    daysInMonth: state => state.date.daysInMonth()
  },
  mutations: {
    subtractOneDay(state) {
        state.date = state.date.clone().subtract(1, 'days');
    }
  }
})

new Vue({
  el: "#app",
  store,
  computed: Object.assign(Vuex.mapGetters(['date', 'daysInMonth']), {}),
  methods:{
    subtractOneDay(){
      this.$store.commit('subtractOneDay');
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  {{date}}
  <hr>
  {{daysInMonth}}
  <hr>
  <button @click="subtractOneDay">Subtract 1 Day</button>
</div>