为什么即使我没有将 vuex 状态绑定到任何 html 输入元素,我的 vuex 状态也会随着组件级状态的改变而改变?

Why does my vuex state change on changing my component level state even if I have not binded the vuex state to any html input element?

我有一个 vue 商店,其中包含以下内容

store.js

import Vue from 'vue'
import Vuex from 'vuex'

const state = {
      supplementStore: {}
    }

const actions = {
  getDataFromApi ({dispatch, commit}) {
    APIrunning.then(response => {
      commit('SET_SUPPLEMENT', response)
    })
  }
}

const mutations = {
  SET_SUPPLEMENT (state, data) {
    state.supplementStore= data
  }
}

const foodstore = {
  namespaced: true,
  state,
  actions,
  mutations
}

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    foodstore
  }
})

我的 vue 组件是这样的

Supp.vue

<template>
    <input type="checkbox" v-model="supps.logged">
</template>

<script>
import {mapState, mapActions} from 'vuex'
import store from './store'

export default {
  data () {
    return {
      supps: []
    }
  },
  mounted () {
    this.supps = this.supplementStore
  },
  computed: {
    ...mapState('foodstore', ['supplementStore'])
  }
}
</script>

如您所见,我有一个名为 supps 的组件级状态,一旦它是 mounted,它就会被分配 supplementStore 的值(这是一个 vuex 状态)。

mounted () {
  this.supps = this.supplementStore
},

supplementStore 从 API 获取它的值,它是一个 JSON 对象,看起来像这样

supplementStore = {
  logged: true
}

因此,当我的 Supp.vue 组件被安装时,我的本地状态 supps 将变为

supps = {
    logged: true
  }

supps 使用 v-model 指令绑定到类型为复选框 (Supp.vue) 的输入字段。

What I want to achieve:

当我切换复选框时,supps.logged 应该在 truefalse 之间切换,但是 supplementStore.logged 应该保持不变(因为我没有将它绑定到我的输入场)。

What I observe in my Vue Devtools:

当我切换复选框时,supps.loggedsupplementStore.logged 都同步切换,即它们都在 true 和 false 之间同步切换,而我只想 supps.logged切换。

谁能帮帮我?

在Javascript中,对象通过引用传递。 (这是一个相当不错的解释=> https://medium.com/nodesimplified/javascript-pass-by-value-and-pass-by-reference-in-javascript-fcf10305aa9c

为避免此问题,您可以在分配给 supps 时克隆对象。

mounted () {
  this.supps = { ...this.supplementStore } // cloning the object using Javascript Spread syntax
},

您尝试过 Object.assign 吗?在 JS 中,对象是通过引用传递的。给一个变量赋值,如果变量里面改了,原来的也会变。

要克隆一个对象,你可以试试这个:

// this.assignedObj = new object. 
// this.obj = original object.
this.assignedObj = Object.assign({}, this.obj);

JSFiddle:https://jsfiddle.net/mr7x4yn0/

编辑:从演示中可以看出,Vue.setthis.$set 对您不起作用(可能)。

我从 API 接收到 supplementStore 的数据采用对象数组的形式:

supplementStore =  [
    {
        "logged": true
    },
    {
        "logged": false
    }
]

正如 Jacob Goh 和 Yousof K. 在各自的回答中提到的,对象和数组在 javascript 中通过引用传递,我决定使用以下代码来分配 supplementStore 的值在我的 mounted() 挂钩中 supps

mounted () {
    let arr = []
      for (let i = 0; i < this.supplementStore.length; i++) {
        let obj = Object.assign({}, this.supplementStore[i])
        arr.push(obj)
      }
      this.supps = arr

  }

现在,当我切换复选框时,supplementStore.logged 保持不变,而 supps.logged 按照我想要的方式在 true 和 false 之间切换。