Почему мое состояние vuex изменяется при изменении состояния уровня моего компонента, даже если я не связал состояние vuex с каким-либо элементом ввода html? - PullRequest
0 голосов
/ 11 мая 2019

У меня есть магазин 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, которому присваивается значение supplementStore (которое является состоянием vuex), как только оно становится mounted.

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

supplementStore получает свое значение от API, и это объект JSON, который выглядит следующим образом

supplementStore = {
  logged: true
}

Поэтому, когда мой Supp.vue компонент смонтирован, мое локальное состояние supps станет

supps = {
    logged: true
  }

supps привязывается к полю ввода типа checkbox (Supp.vue) с использованием директивы v-model.

Чего я хочу достичь:

Когда я переключаю флажок, supps.logged должен переключаться между true и false, но supplementStore.logged должен оставаться неизменным (так как я не связал его с моим полем ввода).

Что я наблюдаю в моем Vue Devtools:

Когда я переключаю флажок, оба supps.logged И supplementStore.logged переключаются синхронно, т. Е. Оба они синхронизируются между истиной и ложью, тогда как я хочу, чтобы только supps.logged переключался.

Кто-нибудь может мне помочь?

Ответы [ 3 ]

2 голосов
/ 11 мая 2019

В 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
},
1 голос
/ 11 мая 2019

Вы пробовали Object.assign вместо этого? В JS объекты передаются по ссылке. Присвоение переменной переменной приведет к изменению исходной переменной при изменении переменной внутри.

Чтобы клонировать объект, вы можете попробовать это:

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

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

Редактировать: Как видно из демонстрации, Vue.set или this.$set не будут работать для вас (вероятно).

0 голосов
/ 11 мая 2019

Данные, которые я получал от API в supplementStore, представляли собой массив объектов:

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

И, как Джейкоб Го и Юсоф К. упомянули в своих соответствующих ответах, что объекты и массивы передаются по ссылке в javascript, я решил использовать следующий код для присвоения значения supplementStore supps внутри моего 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

  }

Теперь, когда я переключаю свой флажок, supplementStore.logged остается неизменным, в то время как supps.logged переключается между истиной и ложью так, как я хотел.

...