如何在Vue3中使用useForm动态创建表单元素并绑定表单数据
解决方案
核心问题说明
你当前通过原生DOM API手动创建输入元素的方式,无法被Vue响应式系统识别,自然不能实现双向绑定。同时初始化的useForm仅配置了单组固定字段,无法存储多组动态生成的输入数据。
改造步骤
第一步:调整useForm初始化结构
将单组字段改为支持多组存储的数组结构:
setup() { const form = useForm({ title: null, regions: [] // 所有动态输入组都存在这个数组中,每组包含selectedText、start、stop三个字段 }) return {form} }
第二步:修改模板为动态列表渲染
把region_block内硬编码的固定region块删除,替换为v-for循环渲染:
<div id="region_block" ref="reg_block" > <div class="region" v-for="(region, index) in form.regions" :key="region.id"> <div class="regionTitle" :style="{color: region.titleColor, fontWeight: 'bold'}"> {{ region.id }} </div> <div class="copyTextButton"> <Button @click="getText(index)" type="button" class="inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring focus:ring-gray-300 disabled:opacity-25 transition">Copy Marked Text</Button> </div> <div class="pp_new_transcript flex flex-col"> <label style="font-weight: bold"> New Transcript: </label> <textarea rows="5" class="selectedTextInput h-full" v-model="form.regions[index].selectedText" /> </div> <div class="pp_start-stop"> <label for="start" style="font-weight: bold"> Start: </label> <input v-model="form.regions[index].start" disabled/> <label for="stop" style="font-weight: bold"> Stop: </label> <input v-model="form.regions[index].stop" disabled/> </div> <div class="submit_button"> <Button class="inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring focus:ring-gray-300 disabled:opacity-25 transition">Submit</Button> </div> </div> </div>
第三步:替换手动创建DOM的逻辑
删除region-created事件中所有手动创建DOM的代码,改为往regions数组新增对象:
wavesurfer.on('region-created', (region, e) => { const color = () => Math.random() * 256 >> 0; const r = color(), g = color(), b = color() this.form.regions.push({ id: region.id, selectedText: '', start: region.start, stop: region.end, titleColor: `rgb(${r},${g},${b})` }) region.color = `rgba(${r},${g},${b}, 0.1)` })
第四步:改造方法适配多组数据
修改方法支持按索引更新对应组的数据:
methods: { getText(index) { this.newTranscript = window.getSelection().toString(); this.form.regions[index].selectedText = this.newTranscript; this.form.title = this.title; }, copyValues(index, start, stop) { this.form.regions[index].start = start; this.form.regions[index].stop = stop; }, // 剩余goBack方法不变 }
第五步:适配region点击事件
点击region时找到对应索引更新时间:
wavesurfer.on('region-click', (region, e) => { e.stopPropagation(); if (play) { wavesurfer.pause(); play = false; } else { region.play(); play = true; } // 找到当前region对应的数组索引 const activeIndex = this.form.regions.findIndex(item => item.id === region.id) if(activeIndex > -1) { this.copyValues(activeIndex, region.start, region.end); } });
提交说明
表单提交时,form.regions数组会自动携带所有组的输入数据,后端直接解析该数组即可获取全部录入内容。
内容的提问来源于stack exchange,提问作者ToroLoco
相关产品推荐
相关产品推荐

