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(String
、Number
、BigInt
、Boolean
、undefined
和 undefined
和 null
)被复制按值,而@987654322 @(包括Array
、Map
、WeakMap
、Set
、WeakSet
)被复制引用。
this.question.title
是一个String
,因此它会按值复制到新变量中。另一方面,this.question.options
是一个对象(它看起来像一个Array
),所以它通过引用复制到questionOptions
,因此questionOptions
和this.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的主要内容,如果未能解决你的问题,请参考以下文章
使用Typescript和类组件装饰器时如何将数组传递给Vue中的props
Vue.js - 如何将 prop 作为 json 数组传递并在子组件中正确使用?