简体   繁体   English

为什么即使我尚未将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?

I have a vue store which has the following 我有一家vue商店,其中有以下商店

store.js 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
  }
})

My vue component looks like this 我的Vue组件看起来像这样

Supp.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>

As you can see I have a component level state called supps which is assigned the value of supplementStore (which is a vuex state) as soon as it is mounted . 正如你可以看到我有一个组件级状态称为supps被分配的值supplementStore (这是一个vuex状态),只要它被mounted

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

supplementStore gets its value from the the API and it is a JSON object which looks like this supplementStore从API获取其值,并且它是一个JSON对象,看起来像这样

supplementStore = {
  logged: true
}

Therefore, when my Supp.vue component is mounted my local state supps will become 因此,当我的Supp.vue组件安装后,我的本地状态supps将变为

supps = {
    logged: true
  }

supps is binded to an input field of type checkbox (Supp.vue) using the v-model directive. supps使用v-model指令绑定到类型为checkbox (Supp.vue)的输入字段。

What I want to achieve: 我要实现的目标:

When I toggle the checkbox, supps.logged should toggle between true and false but, supplementStore.logged should remain unchanged (since I have not binded it to my input field). 当我切换复选框时, supps.logged应该在truefalse之间切换,但是supplementStore.logged应该保持不变(因为我尚未将其绑定到我的输入字段)。

What I observe in my Vue Devtools : 我在Vue Devtools观察到的Vue Devtools

When I toggle the checkbox, both supps.logged AND supplementStore.logged are toggling in sync ie both of them are toggling in sync between true and false, whereas I want only supps.logged to get toggled. 当我切换复选框时, supps.loggedsupplementStore.logged都在同步切换,即它们都在真与假之间同步切换,而我只希望supps.logged被切换。

Can anyone help me? 谁能帮我?

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

To avoid this problem, you can clone the object when assigning to supps . 为避免此问题,可以在分配给supps时克隆对象。

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

Have you tried Object.assign instead? 您是否尝试过Object.assign In JS objects are passed by reference. 在JS中,对象是通过引用传递的。 Assigning one to a variable will cause the original one to change if the variable is changed inside. 如果在变量内进行更改,则为变量分配一个将导致原始变量更改。

To clone an object, you may try this: 要克隆对象,您可以尝试以下操作:

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

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

Edit: As you can see from the demo, Vue.set or this.$set will not work for you (probably). 编辑:从演示中可以看到, Vue.setthis.$set对您不起作用(可能)。

The data I was receiving from the API into supplementStore was in the form of an array of objects: 我从API接收到的数据存储到supplementStore是对象数组的形式:

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

And as Jacob Goh and Yousof K. mentioned in their respective answers that objects and arrays get passed by reference in javascript, I decided to use the following code to assign the value of supplementStore to supps inside my mounted() hook: 正如雅各吴作栋和Yousof K.在对象和数组获得通过javascript参考通过各自的答案中提到,我决定用下面的代码的值赋给supplementStoresupps我里面mounted()挂钩:

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

  }

Now when I toggle my checkbox, supplementStore.logged remains unchanged while supps.logged toggles between true and false just the way I wanted. 现在,当我切换复选框时, supplementStore.logged保持不变,而supps.logged则按照我想要的方式在true和false之间切换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM