如何在Vue嵌套v-for循环中正确存储radio输入字段值
问题根源
绑定异常是多个写法问题叠加导致的:
- 两层
v-for重名了index和exam变量,内层循环直接覆盖外层作用域的索引值,不仅会导致取选项列表时串题,后续绑定值也会完全错乱 - 单选框
name属性靠自增RadioNumber生成的逻辑不可靠,同一道题的选项name不一致会导致单选互斥失效,加上索引重复,不同题的单选框还会互相干扰 v-model绑定ExamAnswers[index]时用的是内层选项的索引,每道题的选项索引都是从0开始,所有题的第一个选项都会绑定到ExamAnswers[0],提交时数据会互相覆盖:key绑定RandomKey()是错误写法,每次渲染都会生成新key导致DOM重复重绘,输入状态容易丢失
修复方案
1. 区分两层循环的变量名
外层遍历题目时,索引用qIndex、题目对象用question;内层遍历选项时,索引用optIndex、选项对象用option,从根源避免作用域变量覆盖。key用固定规则拼接,不要调用随机函数。
2. 生成可靠的单选框name
同一道题的所有选项name必须完全一致,不同题的name不能重复,直接用题目索引拼接生成即可,不需要额外维护RadioNumber变量。
3. 修正答案绑定规则
答案数组按题目维度存储,ExamAnswers[qIndex]对应第qIndex道题用户选中的答案,不要用选项索引做数组下标。
4. 初始化答案数组
接口返回题目数据后,把ExamAnswers初始化为和题目长度一致的空数组,避免响应式绑定异常。
修复后的模板代码:
<div v-for="(question, qIndex) in FilteredExams[0].Questions" v-show="qIndex < stageNumber" :class="{ dspnone: DspLastItem && qIndex < stageNumber - StageOnChange, }" :key="`question-${qIndex}`" class="flex flex-col gap-5" > <!-- 题目内容 --> <p class="text-secondary-600 font-bold">{{ question.question }}</p> <!-- 选项列表 --> <div v-for="(option, optIndex) in question.Answers" :key="`question-${qIndex}-option-${optIndex}`" class="flex gap-3 items-center" > <input type="radio" :name="`answer-${qIndex}`" :value="option.answer" v-model="ExamAnswers[qIndex]" /> <label class="text-sm text-secondary-600"> {{ option.answer }} </label> </div> </div>
调整后的data配置(删掉不需要的RadioNumber变量):
data() { return { DspLastItem: false, stageNumber: null, StageOnChange: null, StageCount: null, StepCount: [], exams: [], FilteredExams: [], errors: [], ExamAnswers: [], }; }, // 接口请求成功、给FilteredExams赋值后,加一行初始化答案数组 // this.ExamAnswers = new Array(this.FilteredExams[0].Questions.length).fill('')
修复后同题选项可以正常互斥,不同题选项不会互相干扰,最终ExamAnswers数组的第n项就对应第n道题用户选中的答案,索引不会重复,也不会出现数据覆盖问题。
内容的提问来源于stack exchange,提问作者pedram
相关产品推荐
相关产品推荐

