能实现,但需手写解析逻辑+条件渲染+手动收集数据;因小程序平台限制v-model及动态JS执行,官方uni-data-form已废弃,须用:value/@input等受控组件方式基于JSON Schema渲染表单。

uni-app 小程序里怎么用 JSON 配置动态生成表单
直接说结论:能实现,但不能靠 uni-app 自带组件自动绑定,必须手写解析逻辑 + 条件渲染 + 手动收集数据。uni-app 没有 v-model 在小程序平台的完整响应式支持,JSON 表单本质是「配置驱动渲染 + 受控组件」。
为什么 uni-data-form 或第三方库在小程序里大概率不 work
常见踩坑点:很多开发者搜到 uni-data-form(uni-app 官方早期实验性组件)或 Vue 生态的 form-create,但在微信/支付宝小程序编译下会报错或丢失双向绑定——因为这些库重度依赖 eval、Function 构造函数或运行时编译模板,而小程序平台禁止动态执行 JS 字符串,且 uni-app 的 template 编译器不支持动态 tag 名或嵌套 v-for/v-if 组合的复杂推导。
-
uni-data-form已在 HBuilderX 3.9+ 中被标记为废弃,文档下线,实际使用会触发Cannot read property 'map' of undefined - Vue 版本的
form-create依赖render函数 +h,但 uni-app 小程序端的render是预编译的,无法运行时构造 vnode - 所有“一键导入 JSON 渲染表单”的 npm 包,在
mp-weixin平台基本都会因require动态路径或new Function被微信开发者工具拦截
正确做法:手写 FormRender 组件 + JSON Schema 规范
核心是把 JSON 当作纯配置,用 v-for 遍历字段,用 type 字段决定渲染哪个原生组件,并用 :value + @input(或 @blur)手动同步数据。注意:小程序 input/textarea/select 不支持 v-model,必须显式传 value 和监听事件。
示例 JSON 配置片段:
{
"fields": [
{
"key": "username",
"label": "用户名",
"type": "input",
"placeholder": "请输入姓名",
"required": true
},
{
"key": "gender",
"label": "性别",
"type": "picker",
"range": ["男", "女"],
"range-key": "label"
}
]
}
对应组件内关键逻辑:
- 用
data声明一个空对象formData: {},初始值按 JSON 中key自动补全(避免 undefined 报 warning) - 模板中用
(可选)包裹,但字段全部用条件判断:formData[item.key] = e.detail.value" /> - picker 类型必须用
+@change,且需把range转成range-key对应的数组索引,再赋值给formData[item.key] - 日期、时间类型统一用
,值存字符串(如 "2024-05-20"),不要转 Date 对象(小程序 setData 不支持)
容易忽略的兼容性和性能点
小程序 setData 有 10MB 限制且深度监听成本高,动态表单字段多时别直接把整个 JSON 配置塞进 data;更稳妥的是只存用户输入值,配置本身放 const schema = ... 外部常量或通过 props 传入。
- 不要在
v-for中直接调用方法返回 JSX(如:value="getValue(item)"),这会导致频繁重绘;改用计算属性或提前映射好的formData对象 - 微信小程序基础库
下,input的@input在中文输入法下会丢字,必须降级用@blur+confirm-type="done"配合 - 如果 JSON 含条件显示逻辑(如“当 A 选‘是’时显示 B 字段”),不要用
v-if切换 DOM,而是用show样式控制显隐,否则picker等组件会销毁重建导致值丢失 - 表单校验别依赖第三方 validator 插件,用
Array.every()遍历字段 + 自定义规则函数更轻量可靠
最麻烦但最稳的方式:每个字段类型单独封装成子组件(form-input、form-picker),父子通信只传 value 和 @change,彻底隔离小程序平台差异。JSON 配置只是描述结构,不参与逻辑。











