动态渲染题型表单的核心是统一数据结构与v-model绑定路径:使用带type/value/id的数组项,所有题型均v-model="item.value",key须唯一且不依赖index,多选value必须初始化为[],条件显示用响应式key而非v-if,删除后需手动清理校验状态。

动态渲染各种题型表单,核心不是“怎么画出来”,而是“怎么让不同题型共用一套数据结构和校验逻辑”。只要数据模型统一、v-for key 稳、v-model 绑定路径明确,文本题、单选、多选、判断、下拉、日期等就能无缝混排。
数据结构必须用数组 + 对象,每个 item 带 type 和 value
别用对象动态加字段(如 formData.q1、formData.q2),Vue 无法响应式追踪。必须用数组存题项,每项是结构一致的对象:
-
type字段标识题型('text'、'radio'、'checkbox'、'select'、'date'等) -
value是统一值字段:单选存String或Number,多选必须初始化为[],文本题就是String -
id必须唯一(推荐Date.now() + Math.random().toString(36).substr(2, 9)),不能用index当:key - 选项类题型(
radio/checkbox/select)额外带options: [{value: 'A', label: '同意'}],不硬编码进模板
渲染时按 type 分支,但 v-model 始终绑定 item.value
不要为每种题型写独立的 v-model="form.radio1",所有题型都走 v-model="item.value"。这样增删题项时,数据自动对齐,校验规则也能复用。
- 文本题:
<input v-model="item.value"> - 单选题:
<radio-group v-model="item.value"><radio v-for="opt in item.options" :key="opt.value" :value="opt.value">{{ opt.label }}</radio></radio-group> - 多选题:
<checkbox-group v-model="item.value">...</checkbox-group>,注意item.value初始值必须是[],不是null或'' - 下拉选择:
<picker :range="item.options" :range-key="'label'" v-model="item.value"></picker>;若用自定义下拉器(如地区选择),确保其内部也双向绑定到item.value
uni-forms 校验失效?给 <uni-forms-item></uni-forms-item> 加响应式 key
当某题是否显示由其他题答案控制(如“是否住校”为“是”才显示“宿舍号”),仅用 v-if 会导致 uni-forms 内部校验注册丢失——组件销毁后重建,没重新走校验注册流程。
- 错误写法:
<uni-forms-item v-if="formData.isDormitory"></uni-forms-item> - 正确写法:
<uni-forms-item :key="'dormInput_' + formData.isDormitory"></uni-forms-item>,key 随条件变化强制重置组件实例 - 更稳妥:key 包含题型和 id,如
:key="'field_' + item.id + '_' + item.type",避免跨题型复用残留状态 - 别用
<template v-if></template>包裹<uni-forms-item></uni-forms-item>,那只是隐藏 DOM,校验规则仍在注册,反而可能冲突
删除题项后,校验状态要手动重置
uni-forms 不会自动清理已删除项的校验缓存。删掉第 2 个题后,如果原第 3 项变成新第 2 项,它的校验错误提示可能还挂着旧的红边或文字。
- 删除操作后,显式调用
this.$refs.uForm.clearValidate(['fieldId'])(若你用 uView)或this.$refs.uniForms.clearValidate() - 更彻底的做法:删完后调用
this.$nextTick(() => { this.$refs.uniForms.validateField() }),触发一次全量校验刷新 - 如果用了插件如
active-form,检查其文档是否提供removeItem(id)方法,它通常内置了状态清理逻辑
最容易被忽略的是:多选题的 item.value 类型必须始终是数组,哪怕只选一个;还有 :key 的生成逻辑一旦写成 index,删中间项就会导致后续所有 v-model 绑定错位——这两点出问题,80% 的“输入没反应”“删了数据跑偏”就都有了。


















