首页 > 解决方案 > Vue watch 数组推送相同的新旧值

问题描述

我正在使用 Vuex,我创建了一个名为 Claims 的模块,如下所示:

import to from 'await-to-js'
import { functions } from '@/main'
import Vue from 'vue'

const GENERATE_TX_SUCCESS = 'GENERATE_TX_SUCCESS'
const GENERATE_TX_ERROR = 'GENERATE_TX_ERROR'

export default {
  state: [ ],
  mutations: {
    [GENERATE_TX_SUCCESS] (state, generateTxData) {
      state.push({ transaction: { ...generateTxData } })
    },
    [GENERATE_TX_ERROR] (state, generateTxError) {
      state.push({ transaction: { ...generateTxError } })
    }
  },
  actions: {
    async generateTx ({ commit }, data) {
      const [generateTxError, generateTxData] = await to(functions.httpsCallable('generateTx')(data))
      if (generateTxError) {
        commit(GENERATE_TX_ERROR, generateTxError)
      } else {
        commit(GENERATE_TX_SUCCESS, generateTxData)
      }
    }
  },
  getters: { }
}

然后,在 .vue 组件中,我确实有这个手表:

 watch: {
    claims: {
      handler (newTxData, oldTxData) {
        console.log(newTxData)
      }
    }
 }

我在这里面临的问题是 newTxData 与 oldTxData 相同。

据我了解,由于这是一个推送并且它检测到更改,所以它不是这些警告之一:https ://vuejs.org/v2/guide/list.html#Caveats

所以基本上问题是这个:

注意:当改变(而不是替换)对象或数组时,旧值将与新值相同,因为它们引用相同的对象/数组。Vue 不保留 pre-mutate 值的副本。

https://vuejs.org/v2/api/#vm-watch

那么我的问题是:我应该如何在突变中解决这个问题?

编辑

我也尝试过,Vue.set(state, state.length, generateTxData)但得到了相同的行为。

编辑 2 -临时解决方案- (性能不佳):

我正在使用vuexfire 使@matthew(感谢 @Jacob Goh)适应我的解决方案:

computed: {
  ...mapState({
    claims: state => cloneDeep(state.claims)
  })
},

标签: arraysvue.jsvuejs2vuexvuexfire

解决方案


这个答案基于@matthew 这个非常聪明的答案

您将需要lodash cloneDeep功能

基本上,创建一个这样的计算值

computed: {
    claimsForWatcher() {
        return _.cloneDeep(this.claims);
    }
}

发生的情况是,每次推入一个新值claimsclaimsForWatcher都会成为一个全新的对象

因此,当您观看时claimsForWatcher,您将不会再遇到“旧值将与新值相同,因为它们引用相同的对象/数组”的问题。

watch: {
    claimsForWatcher(oldValue, newValue) {
        // now oldValue and newValue will be 2 entirely different objects
    }
}

警告:随着数据的增长,这会带来性能成本


推荐阅读