不要编辑作为道具传递给组件的v-data



我使用next2.15.3

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

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

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

<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数据对象时,只有在编辑问题选项?

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

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

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

在JavaScript中,原语(String,Number,BigInt,Boolean,undefinednull)通过值复制,而对象(包括Array,Map,WeakMap,Set,WeakSet)通过引用复制

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

克隆传入的this.question.options的想法是正确的解决方案,但是Object.assign()和扩展操作符只创建仍然引用相同原始对象的浅拷贝,这解释了当组件试图修改浅拷贝时Vuex状态突变警告。

有几种方法可以深度复制对象,其中一种方法在这里的另一个答案中提供:
export default {
data() {
return {
questionTitle: this.question.title,
questionOptions: JSON.parse(JSON.stringify(this.question.options))
}
}
}

演示

尝试制作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>

最新更新