Vue编辑已作为prop传递给组件的v-data

Posted

技术标签:

【中文标题】Vue编辑已作为prop传递给组件的v-data【英文标题】:Vue editing v-data that has been passed to a component as a prop 【发布时间】:2021-10-21 10:35:40 【问题描述】:

我正在使用 Nuxt 2.15.3

在我的应用中,用户可以设置客户可以回答的问题,问题可以是多种类型,其中之一是多项选择题。这些类型的问题有一个标题,以及可供人们选择的多个答案选项。

在我的问题页面上,我列出了用户的所有问题,并且我希望允许他们编辑任何问题,但我在弄清楚如何准确地做到这一点时遇到了一些麻烦,至少在编辑多个问题时选择题。就目前而言,我有一个 EditQuestion 组件,我从我的 QuestionCard 组件传递了一个 question 道具,道具只是存储在 Vuex 中的问题的详细信息。

我当前(简化为 SO)版本的 EditQuestion 组件:

<template>
  <input v-model="questionTitle" type="text">
  <div v-if="question.type === 'multiple_choice'">
    <input v-for="option in questionOptions" v-model="option.content" type="text">
  </div>
  <button @click.prevent="updateQuestion"></button>
</template>

<script>
  export default 
    props: 
      question: 
    ,
    data() 
      return 
        questionTitle: this.question.title,
        questionOptions: this.question.options
      
    ,
    methods: 
      updateQuestion() 
        // Call the API with the new question details
      
    
  
</script>

如果我只是在编辑问题标题,那效果很好。但是,我的问题来自选项。如果我尝试更新一个,Vuex 会警告我在突变之外改变存储状态,即使我克隆 question.options,它也会警告我,例如通过执行 questionOptions: Object.assign(, this.question.options)questionOptions: ...this.question.options. 混淆的部分我就是为什么 Vuex 在我修改 questionTitle 数据对象时没有抱怨,并且只有在编辑 questionOptions 时才抱怨?

如果相关,请作为参考,question.title 只是一个简单的字符串,而question.options 是一个看起来像这样的对象:


  "0": 
    "id": 0,
    "content": "Option 1"
  ,
  "1": 
    "id": 1,
    "content": "Option 2"
  

对我来说,允许人们编辑多项选择题选项的最佳方式是什么?

【问题讨论】:

你尝试过使用 Lodash 的cloneDeep 方法吗?因为它可能在抱怨,因为您正在尝试修改对象的引用。而是克隆所有对象并更新副本而不是引用。这里没有显示 Vuex,但通常这种事情直接在 Vuex 动作中完成时很好。 【参考方案1】:

javascript 中,primitives(StringNumberBigIntBooleanundefinedundefinednull)被复制按值,而@987654322 @(包括ArrayMapWeakMapSetWeakSet)被复制引用

this.question.title 是一个String,因此它会按值复制到新变量中。另一方面,this.question.options 是一个对象(它看起来像一个Array),所以它通过引用复制到questionOptions,因此questionOptionsthis.question.options 在 Vuex 中指的是同一个对象。

您克隆传入的this.question.options 的想法是正确的解决方案,但Object.assign() 和spread operator 只创建仍然引用相同原始对象的浅表副本,这解释了Vuex 状态突变当您的组件尝试修改浅拷贝时发出警告。

ways to deep-copy an object有几个,the other answer here中提供了一个:

export default 
  data() 
    return 
      questionTitle: this.question.title,
      questionOptions: JSON.parse(JSON.stringify(this.question.options))
    
  

demo

【讨论】:

【参考方案2】:

尝试制作question 对象的本地副本并仅在该本地副本上执行所有更新,如下所示:

<script>
  export default 
    props: 
      question: 
    ,
    data() 
      return 
        localCopyOfQuestion: JSON.parse(JSON.stringify(this.question)),
        questionTitle: this.localCopyOfQuestion.title,
        questionOptions: this.localCopyOfquestion.options
      
    ,
    methods: 
      updateQuestion() 
        // Call the API with the new question details
      
    
  
</script>

【讨论】:

以上是关于Vue编辑已作为prop传递给组件的v-data的主要内容,如果未能解决你的问题,请参考以下文章

使用当前 vue 组件的方法作为默认 prop 值

使用Typescript和类组件装饰器时如何将数组传递给Vue中的props

Vue2将任意命名变量作为道具传递

Vue.js - 如何将 prop 作为 json 数组传递并在子组件中正确使用?

在 Vue 3 Typescript 中将道具传递给数据对象

如何访问子组件内部传递的prop数组