更新记录
1.0.2(2025-08-08)
修复了bug
1.0.1(2025-08-08)
1.0.1
- 修复了bug
1.0.0(2025-08-07)
组件介绍
- 通过Json配置驱动的表单组件,支持多种表单元素,如文本框、选择框、日期选择器等,可以轻松实现复杂的表单布局和交互。
✨ 表单支持
- 单行文本输入框
- 多行文本输入框
- 单选按钮
- 多选按钮
- 下拉选择框
- 日期选择器
- 时间选择器
- 数字输入框
- 开关按钮
- 复选框
- 图片上传
- 颜色选择器
- 城市地区选择器
平台兼容性
uni-app x(4.76)
Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
---|---|---|---|---|---|
√ | - | 5.0 | - | - | - |
meta-json-forms 万能Json驱动表单
一个通过json数据驱动的表单组件,你只需按规范配置JSON数据,就能动态配置各种表单,涵盖了大部分表单场景,如:文本输入框、时间选择、日期选择、颜色选择、城市地区、多选与单选等。满足你的任何数据需求,减少重复性代码,提高你的工作效率。
作者的话
开发这个组件目的是给大家减少重复性代码,提高开发效率,如果你有好的建议或者需求,欢迎在插件市场留言反馈,我会及时更新。如果对你有用希望你可以支持一下我哦!就当请我吃个盒饭。
兼容性
目前此版本只支持uniappX,测试安卓与网页版无问题,其他平台按理说应该没问题,但未测试,如有问题请留言反馈。
预览
组件用途
- 1.用于动态页面,根据后台返回的json数据,动态生成表单
- 2.开发小工具,如:问卷调查、订单填写、个人信息修改等
- 3.内置多种选择器,如时间选择器、日期选择器、城市地区选择器与颜色选择器等,满足各种场景需求
- 4.有能力的话可以对组件进行再封装,通过数据库驱动组件,实现get/post请求,动态获取表单数据,实现更灵活的表单功能
功能特点
- 支持多种表单类型,满足各种场景需求
- 支持表单验证,确保数据准确性
- 支持表单数据缓存,方便下次使用
- 支持表单数据导出
表单类型支持
- 单行文本输入框
- 多行文本输入框
- 单选按钮
- 多选按钮
- 下拉选择框
- 日期选择器
- 时间选择器
- 日历选择器
- 数字输入框
- 开关按钮
- 复选框
- 图片上传
- 颜色选择器
- 城市地区选择器
安装方法
在插件市场中搜索并导入 meta-json-forms
,或者直接通过插件市场导入。
基础用法
<template>
<scroll-view class="content">
<meta-json-forms ref="metaJsonForms" :formData="formConfig" keyName="user_form"
@change="onChange"></meta-json-forms>
</scroll-view>
</template>
<script>
import { FormFieldData, FormChangeEvent } from '@/uni_modules/meta-json-forms'
export default {
data() {
return {
formConfig: [
{
key: "username",
name: "用户名",
type: "input",
value: "",
isSave: false,//是否缓存
condition:{ field: 'image', value: 0, operator: '=' },//满足条件显示,图片的value返回是数组,所以只要图片数量满足条件就显示
extra: {
minLength: 2,//限制最小字符数
maxLength: 10,//限制最大字符数
placeholder: "请输入用户名",//输入框占位提示
tip: "用户名限制2~10个字符",//表单说明
inputmode: "text" //none | search | email | url | text | number | idcard | digit | tel | safe-password | nickname
}
},
{
key: "introduction",
name: "个人介绍",
type: "textarea",
value: "",
isSave: false,
condition: {
or:[ //有or就有and,or是只要其中一项满足就显示
{ field: 'appointmentTime', value: "10:00", operator: 'before' },//时间10:00之前满足条件,也可以填写日期2025-08-07,这样比较就是2025-08-07之前,支持after和sameDay
{ field: 'image', value: 0, operator: '=' }//图片数量大于3
],
// and:[]所以条件满足才显示,有and条件时,or条件不生效
},
extra: {
minLength: 6,
maxLength: 20,//-1为不限
placeholder: "请介绍下自己",
tip: ""
}
},
{
key: "region",
name: "居住地",
type: "region",
value: "",
isSave: false,
condition:false,//为false时不显示,也可以为0或1,这样可以自己写逻辑控制表单隐藏和显示
extra: {
level: 3,//1为省份 2为省份-市区选择 3为省份-市区-区县
separator: "-",//分隔符
title: "选择地区",//弹窗标题
placeholder: "请选择地区",//默认占位符
tip: "地区选择"
}
},
{
key: "image",
name: "图片选择",
type: "image",
value: "",
extra: {
columnCount: 4,//图片列数
limit: 6, // 最多选择6张图片,为1时value默认为字符串,大于1时value默认为图片地址数组
sourceType: ["album", "camera"], // 图片来源 album相册 camera相机
sizeType: ["original", "compressed"] // 图片尺寸 original原图 compressed压缩
}
},
{
key: "advantage",
name: "优点",
type: "multiselect",
value: "",
isSave: false,
extra: {
displayType: "popup",//popup | checkbox
checkboxColor: "#ff6b35",//checkbox选中的颜色
delimiter: "-",//选中结果分隔符
tip: "请选择您的优点",
placeholder: "选择你的优点",
layoutDirection: "vertical",//选项的布局方向 vertical为竖向 horizontal为横向
options: [
{ "text": "细心", "value": "细心" },
{ "text": "有耐心", "value": "有耐心" },
{ "text": "喜欢探索", "value": "喜欢探索" },
{ "text": "情商高", "value": "情商高" }
]
}
},
{
key: "interests",
name: "兴趣爱好",
type: "multiselect",
value: "",
isSave: false,
extra: {
displayType: "checkbox",//popup | checkbox
checkboxColor: "#ff6b35",//checkbox选中的颜色
delimiter: "-",//选中结果分隔符
tip: "请选择您的兴趣爱好",
placeholder: "选择你的兴趣爱好",
layoutDirection: "vertical",//选项的布局方向 vertical为竖向 horizontal为横向
options: [
{ "text": "阅读", "value": "reading" },
{ "text": "音乐", "value": "music" },
{ "text": "电影", "value": "movie" },
{ "text": "旅行", "value": "travel" }
]
}
},
{
key: "married",
name: "是否已婚",
type: "switch",
value: false,
isSave: false,
extra: {
"varType": "boolean",//number |boolean
"tip": "开启后将启用此功能"
}
},
{
key: "age",
name: "年龄",
type: "slider",
value: 20,
isSave: false,
extra: {
"min": 18,
"max": 45,
"step": 1,
"activeColor": "#ff557f",
"sliderBackgroundColor": "#000000",
"blockColor": "#8A6DE9",
"blockSize": 35
}
},
{
key: "workYear",
name: "工作时间",
type: "numberbox",
value: 1,
isSave: false,
extra: {
"min": 1,
"max": 30,
"step": 1,
"unit": "年",//单位
"tip": "请选择年数"
}
},
{
key: "color",
name: "喜欢颜色",
type: "color",
value: "",
isSave: false,
extra: {
"varType": "hex",//hex |rgba
"tip": "选择您喜欢的主题颜色"
}
},
{
key: "city",
name: "所在城市",
type: "select",
value: "",
isSave: true,
extra: {
"varType": "string",//string|int|float
"placeholder": "请选择城市",
"tip": "选择您所在的城市",
"options": [
{ "text": "北京", "value": "beijing" },
{ "text": "上海", "value": "shanghai" },
{ "text": "广州", "value": "guangzhou" },
{ "text": "深圳", "value": "shenzhen" },
{ "text": "杭州", "value": "hangzhou" }
]
}
},
{
key: "birthday",
name: "生日",
type: "calendar",
value: "",
isSave: true,
extra: {
"tip": "请选择生日日期"
}
},
{
key: "appointmentTime",
name: "预约时间",
type: "datetime",
value: "",
isSave: false,
extra: {
"varType": "datetime", //'datetime' | 'date' | 'time' | 'year' | 'year-month' | 'month' | 'day' | 'hour-minute' | 'hour-minute-second' | 'datetime-range' | 'date-range' | 'time-range'
"tip": "请选择预约的日期和时间"
}
},
{
key: "gender",
name: "性别选择",
type: "radio",
value: "male",
isSave: true,
extra: {
"varType": "string",//string |number
"radioColor": "#007aff",
"layoutDirection": "horizontal",//选项的布局方向 vertical为竖向 horizontal为横向
"tip": "请选择您的性别",
"options": [
{ "text": "男", "value": "male" },
{ "text": "女", "value": "female" },
{ "text": "其他", "value": "other" }
]
}
}
] as FormFieldData[]
}
},
methods: {
onChange(e : FormChangeEvent) {
console.log(e)
}
}
}
</script>
<style>
.content {
height: 100%;
}
.meta-custom-class-region .region-display-container{
background-color: blue !important;
}
</style>
弹窗模式
<template>
<view class="content">
<meta-json-forms-dialog ref="metaJsonFormsDialog" @confirm="onConfirm" />
<button class="test-button" @click="viewForm">查看表单</button>
</view>
</template>
<script>
import { FormFieldData, FormChangeEvent } from '@/uni_modules/meta-json-forms'
export default {
data() {
return {
formConfig: [
{
key: "username",
name: "用户名",
type: "input",
value: "",
isSave: false,//是否缓存
extra: {
minLength: 2,//限制最小字符数
maxLength: 10,//限制最大字符数
placeholder: "请输入用户名",//输入框占位提示
tip: "用户名限制2~10个字符",//表单说明
inputmode: "none" //none | search | email | url | text | number | idcard | digit | tel | safe-password | nickname
}
},
{
key: "introduction",
name: "个人介绍",
type: "textarea",
value: "",
isSave: false,
extra: {
minLength: 6,
maxLength: 20,//-1为不限
placeholder: "请介绍下自己",
tip: ""
}
},
{
key: "region",
name: "居住地",
type: "region",
value: "",
isSave: false,
extra: {
level: 3,//1为省份 2为省份-市区选择 3为省份-市区-区县
separator: "-",//分隔符
title: "选择地区",//弹窗标题
placeholder: "请选择地区",//默认占位符
tip: "地区选择"
}
},
{
key: "image",
name: "图片选择",
type: "image",
value: "",
extra: {
columnCount: 4,//图片列数
limit: 6, // 最多选择6张图片,为1时value默认为字符串,大于1时value默认为图片地址数组
sourceType: ["album", "camera"], // 图片来源 album相册 camera相机
sizeType: ["original", "compressed"] // 图片尺寸 original原图 compressed压缩
}
},
{
key: "advantage",
name: "优点",
type: "multiselect",
value: "",
isSave: false,
extra: {
displayType: "popup",//popup | checkbox
checkboxColor: "#ff6b35",//checkbox选中的颜色
delimiter: "-",//选中结果分隔符
tip: "请选择您的优点",
placeholder: "选择你的优点",
layoutDirection: "vertical",//选项的布局方向 vertical为竖向 horizontal为横向
options: [
{ "text": "细心", "value": "细心" },
{ "text": "有耐心", "value": "有耐心" },
{ "text": "喜欢探索", "value": "喜欢探索" },
{ "text": "情商高", "value": "情商高" }
]
}
},
{
key: "interests",
name: "兴趣爱好",
type: "multiselect",
value: "",
isSave: false,
extra: {
displayType: "checkbox",//popup | checkbox
checkboxColor: "#ff6b35",//checkbox选中的颜色
delimiter: "-",//选中结果分隔符
tip: "请选择您的兴趣爱好",
placeholder: "选择你的兴趣爱好",
layoutDirection: "vertical",//选项的布局方向 vertical为竖向 horizontal为横向
options: [
{ "text": "阅读", "value": "reading" },
{ "text": "音乐", "value": "music" },
{ "text": "电影", "value": "movie" },
{ "text": "旅行", "value": "travel" }
]
}
},
{
key: "married",
name: "是否已婚",
type: "switch",
value: false,
isSave: false,
extra: {
"varType": "boolean",//number |boolean
"tip": "开启后将启用此功能"
}
},
{
key: "age",
name: "年龄",
type: "slider",
value: 20,
isSave: false,
extra: {
"min": 18,
"max": 45,
"step": 1,
"activeColor": "#ff557f",
"sliderBackgroundColor": "#000000",
"blockColor": "#8A6DE9",
"blockSize": 35
}
},
{
key: "workYear",
name: "工作时间",
type: "numberbox",
value: 1,
isSave: false,
extra: {
"min": 1,
"max": 30,
"step": 1,
"unit": "年",//单位
"tip": "请选择年数"
}
},
{
key: "color",
name: "喜欢颜色",
type: "color",
value: "",
isSave: false,
extra: {
"varType": "hex",//hex |rgba
"tip": "选择您喜欢的主题颜色"
}
},
{
key: "city",
name: "所在城市",
type: "select",
value: "",
isSave: true,
extra: {
"varType": "string",//string|int|float
"placeholder": "请选择城市",
"tip": "选择您所在的城市",
"options": [
{ "text": "北京", "value": "beijing" },
{ "text": "上海", "value": "shanghai" },
{ "text": "广州", "value": "guangzhou" },
{ "text": "深圳", "value": "shenzhen" },
{ "text": "杭州", "value": "hangzhou" }
]
}
},
{
key: "appointmentTime",
name: "预约时间",
type: "datetime",
value: "",
isSave: false,
extra: {
"varType": "datetime", //'datetime' | 'date' | 'time' | 'year' | 'year-month' | 'month' | 'day' | 'hour-minute' | 'hour-minute-second' | 'datetime-range' | 'date-range' | 'time-range'
"tip": "请选择预约的日期和时间"
}
},
{
key: "gender",
name: "性别选择",
type: "radio",
value: "male",
isSave: true,
extra: {
"varType": "string",//string |number
"radioColor": "#007aff",
"layoutDirection": "horizontal",//选项的布局方向 vertical为竖向 horizontal为横向
"tip": "请选择您的性别",
"options": [
{ "text": "男", "value": "male" },
{ "text": "女", "value": "female" },
{ "text": "其他", "value": "other" }
]
}
}
] as FormFieldData[]
}
},
methods: {
onConfirm(result : UTSJSONObject) {
console.log(result)
},
viewForm() {
(this.$refs['metaJsonFormsDialog'] as ComponentPublicInstance).$callMethod('show', {
title: "表单标题",
formTitle: "用户信息表单",
formData: this.formConfig, // 表单配置数据
confirmText: "提交",
cancelText: "取消",
keyName: "user_form",
extra:{
"msg":"我是携带参数",
"id":"我是id"
}
} as UTSJSONObject);
}
}
}
</script>
<style>
.content {
width: 100%;
height: 100%;
}
.test-button {
margin: 20rpx auto;
width: 600rpx;
background-color: #007AFF;
color: white;
border: none;
border-radius: 8rpx;
padding: 20rpx;
font-size: 28rpx;
}
</style>
condition字段说明
- 该字段可不填写,如果需要某些表单根据某个表单的字段来显示或隐藏,则可以填写该字段
- condition字段支持以下类型:
- boolean:true 或者false 此方式可以自行写逻辑控制表单显示与否
- number:1 或者 0 原理同上
- 单条件object:{ field: 'count', value: 5, operator: '>' } count大于5才显示
- 多条件数组Array:[{ field: 'count', value: 5, operator: '>' }, { field: 'count', value: 10, operator: '<' }] count大于5并且小于10才显示,默认是and关系,也就是所有条件都得满足
- 多条件and-object:{ and: [{ field: 'count', value: 5, operator: '>' }, { field: 'count', value: 10, operator: '<' }] } 效果与上面一样
- 多条件or-object:{ or: [{ field: 'count', value: 5, operator: '>' }, { field: 'sex', value: 'male', operator: '=' }] } 数组当中有一个满足条件就显示
- 当表单中某个字段的值与condition字段中的value满足operator的条件,该表单才会显示,否则隐藏
- 多条件对象有and与or属性同时存在时,优先执行and,or条件会被忽略
- operator支持的运算符有:
- '>':大于
- '<':小于
- '>=':大于等于
- '<=':小于等于
- '=':等于
- '!=':不等于
- 'in':如果指定field的对象值为数组时,则在指定数组中是否存在条件中的value;如果指定对象为string字符串,则表示字符串是否包含value
- 'not in':与上方的相反,指的是不存在该
- 'after':该操作字段只支持日期格式的字符串,例如:2023-01-01,表示大于指定日期
- 'before':该操作字段只支持日期格式的字符串,例如:2023-01-01,表示小于指定日期
- 'sameDay':表示同一天
- 'sameHour':表示同一小时
- 'beforeDays':表示当前日期在 field对应value 日期前 n 天范围内时显示(从 fieldValue-n 天到 fieldValue包含当天)
- 'afterDays':表示当前日期在 fieldValue 日期后 n 天范围内时显示(从 fieldValue 到 fieldValue+n 天)
- 'beforeOutDays':表示当前日期在 fieldValue 日期前 n 天之前时显示(从 fieldValue-n 天之前,包括该天)
- 'afterOutDays':表示当前日期在 fieldValue 日期后 n 天之后时显示(从 fieldValue+n 天之后,包括该天)
- 'aroundDay':表示当前日期在 fieldValue 日期前后 n 天范围内时显示(从 fieldValue-n 天到 fieldValue+n 天)
- 'notAroundDay':表示当前日期不在 fieldValue 日期前后 n 天范围内时显示(在 fieldValue-n 天之前或 fieldValue+n 天之后)
- 注意:after|before|sameDay|sameHour|beforeDays|afterDays|beforeOutDays|afterOutDays|aroundDay|notAroundDay 只支持xxxx-xx-xx xx:xx的格式,例如日期2025-08-01、完整时间2025-08-01 20:00,使用本组件的日期选择器格式无需担心日期格式
- 例如:condition字段示范
const formConfig1 = [ { key: "married", name: "是否已婚", type: "switch", value: false, isSave: false, extra: { "varType": "boolean",//number |boolean "tip": "开启后将启用此功能" } }, { key: "age", name: "年龄", type: "slider", value: 20, isSave: false, extra: { "min": 18, "max": 45, "step": 1 } }, { key: "appointmentTime", name: "预约时间", type: "datetime", value: "", isSave: false, extra: { "varType": "datetime", "tip": "请选择预约的日期和时间" } }, { key: "testA", name: "测试A", type: "input", value: "", isSave: false, condition: { field: 'married', value: true, operator: '=' },//单条件object:满足条件显示,也就是key为married的表单value为true时显示,这里的value支持string、number和boolean extra: { minLength: 2, maxLength: 10, placeholder: "请输入用户名", tip: "用户名限制2~10个字符", inputmode: "text" }
},
{
key: "testB",
name: "测试B",
type: "input",
value: "",
isSave: false,
condition: [{ field: 'married', value: true, operator: '=' }, { field: 'age', value: 25, operator: '>' }],//默认And数组条件,满足所有条件显示,也就是key为married的表单value为true且key为age的表单value大于25时显示,这里的value支持string、number和boolean
extra: {
minLength: 2,
maxLength: 10,
placeholder: "请输入用户名",
tip: "用户名限制2~10个字符",
inputmode: "text"
}
},
{
key: "testC",
name: "测试C",
type: "input",
value: "",
isSave: false,
condition: {
and:[{ field: 'married', value: true, operator: '=' }, { field: 'age', value: 25, operator: '>' }]
},//默认And数组条件,满足所有条件显示,也就是key为married的表单value为true且key为age的表单value大于25时显示,这里的value支持string、number和boolean
extra: {
minLength: 2,
maxLength: 10,
placeholder: "请输入用户名",
tip: "用户名限制2~10个字符",
inputmode: "text"
}
},
{
key: "testD",
name: "测试D",
type: "input",
value: "",
isSave: false,
condition: {
or:[{ field: 'married', value: true, operator: '=' }, { field: 'agappointmentTimee', value: "2025-08-01", operator: 'before' }]
},//默认Or数组条件,满足其中一个条件显示,也就是key为married的表单value为true或者key为agappointmentTimee的表单value时间在2025-08-01之前显示,这里的value支持string、number和boolean
extra: {
minLength: 2,
maxLength: 10,
placeholder: "请输入用户名",
tip: "用户名限制2~10个字符",
inputmode: "text"
}
}
]