为啥即使我没有将 vuex 状态绑定到任何 html 输入元素,我的 vuex 状态也会在更改组件级别状态时发生变化?

Posted

技术标签:

【中文标题】为啥即使我没有将 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?为什么即使我没有将 vuex 状态绑定到任何 html 输入元素,我的 vuex 状态也会在更改组件级别状态时发生变化? 【发布时间】:2019-09-29 00:43:23 【问题描述】:

我有一个 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) 类型的输入字段。

我想要达到的目标:

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

我在Vue Devtools 中观察到的内容:

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

谁能帮帮我?

【问题讨论】:

【参考方案1】:

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
,

【讨论】:

您提供的解决方案似乎不起作用。 supplementStore 还在变化 我有,但实际代码属于我的雇主,因此不能在这里分享。我认为问题在于我的实际代码中的supplementStore 是一个对象数组[ "logged": true , "logged": false ],我在v-for 指令中循环输入复选框字段【参考方案2】:

您是否尝试过Object.assign?在 JS 中,对象是通过引用传递的。给变量赋值1,如果变量内部发生变化,会导致原来的变量发生变化。

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

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

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

编辑:正如您从演示中看到的那样,Vue.setthis.$set 对您不起作用(可能)。

【讨论】:

【参考方案3】:

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

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

正如 Jacob Goh 和 Yousof K. 在他们各自的答案中提到的,对象和数组在 javascript 中通过引用传递,我决定使用以下代码将 supplementStore 的值分配给我的 @987654325 中的 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 按我想要的方式在真假之间切换。

【讨论】:

以上是关于为啥即使我没有将 vuex 状态绑定到任何 html 输入元素,我的 vuex 状态也会在更改组件级别状态时发生变化?的主要内容,如果未能解决你的问题,请参考以下文章

将VueX存储状态值绑定到输入(VueJS)

尽管状态更新,为啥 vuex 组件没有更新?

为啥 Vuex-persist 不在 localStorage 中存储任何内容?

为啥我工作时状态栏没有更新?

为啥 Vuex 状态将数组作为对象返回

为啥输入的值没有传递给 VUEX