我们在写一些常规后台页面的时候,避免不了是需要经常和表单打交道。所以可以想偷懒的小伙伴可能会考虑有没有办法不去做表单工程师
?用代码解决重复的人肉工作,没错,我们可以通过 JSON Schema 来描述我们的表单信息,这比重复的写表单控件可方便多了。
但是 JSON Schema
到表单的映射,则是需要我们去关注的,so... 业界有没有比较好的方案呢?答案是肯定的,比如以下几个表单渲染工具:
Formliy
是一款比较强大的表单渲染器,目前对 React 支持最友好,Vue 相关的有一个 vue-formly 但也仅仅是 Vue 2.x 的。还有就是 Formliy
过于强大,不仅仅支持 JSON Schema 还支持 JSX Schema 渲染表单。而我们只是单纯需要像 Form Render 这样的 JSON Schema 标准的轻量易用型框架。所以 有了这个 基于 Vue 3.x 的 Form render
vue-form-render
是基于 Form Render 基本能力作为原型实现的 Vue 3.x
版本的表单渲染器,目前支持 90% 左右的 Form Render
功能,后续会不断的维护支持。
<template>
<div>
<formRender
:schema="schema"
:formData="formData"
@on-change="change"
@on-validate="validate"
/>
</div>
</template>
<script>
import {reactive, toRefs} from 'vue';
// render index
import FormRender from 'kaer-form-render';
// form render style
import 'kaer-form-render/lib/kaer-form-render.css';
export default {
name: 'App',
setup() {
const state = reactive({
schema: {
type: 'object',
properties: {
string: {
title: 'string',
type: 'string',
maxLength: 4,
}
},
},
formData: {
string: 'aaa'
},
});
const change = (v) => {
state.formData = v;
console.log(v);
}
const validate = (v) => {
console.log(v);
}
return {
...toRefs(state),
change,
validate,
}
},
components: {
FormRender,
}
}
</script>
excel
导入数据,方便快快捷生成form Data
"listName2": {
"title": "对象数组",
"description": "对象数组嵌套功能",
"type": "array",
"minItems": 1,
"maxItems": 3,
"ui:displayType": "row",
"items": {
"type": "object",
"properties": {
"input1": {
"title": "简单输入框",
"type": "string"
},
"selet1": {
"title": "单选",
"type": "string",
"enum": [
"a",
"b",
"c"
],
"enumNames": [
"早",
"中",
"晚"
]
}
}
}
}
"string": {
"title": "字符串",
"type": "string",
"maxLength": 4,
"ui:options": {
"placeholder": "试着输入超过 4 个字符"
}
}
"color": {
"title": "颜色选择",
"type": "string",
"format": "color"
}
"date": {
"title": "日期选择",
"type": "string",
"format": "date"
}
"image": {
"title": "图片展示",
"type": "string",
"format": "image"
}
"allNumber": {
"title": "number 类",
"type": "object",
"properties": {
"number1": {
"title": "数字输入框",
"description": "1 - 1000",
"type": "number",
"min": 1,
"max": 1000
},
"number2": {
"title": "带滑动条",
"type": "number",
"ui:widget": "slider"
}
}
}
"allBoolean": {
"title": "boolean 类",
"type": "object",
"properties": {
"radio": {
"title": "是否通过",
"type": "boolean"
},
"switch": {
"title": "开关控制",
"type": "boolean",
"ui:widget": "switch"
}
}
}
"allRange": {
"title": "range 类",
"type": "object",
"properties": {
"dateRange": {
"title": "日期范围",
"type": "range",
"format": "dateTime",
"ui:options": {
"placeholder": [
"开始时间",
"结束时间"
]
}
}
}
}
"allEnum": {
"title": "选择类",
"type": "object",
"properties": {
"select": {
"title": "单选",
"type": "string",
"enum": [
"a",
"b",
"c"
],
"enumNames": [
"早",
"中",
"晚"
]
},
"radio": {
"title": "单选",
"type": "string",
"enum": [
"a",
"b",
"c"
],
"enumNames": [
"早",
"中",
"晚"
],
"ui:widget": "radio"
},
"multiSelect": {
"title": "多选",
"description": "下拉多选",
"type": "array",
"items": {
"type": "string"
},
"enum": [
"A",
"B",
"C",
"D"
],
"enumNames": [
"杭州",
"武汉",
"湖州",
"贵阳"
],
"ui:widget": "multiSelect"
},
"boxes": {
"title": "多选",
"description": "checkbox",
"type": "array",
"items": {
"type": "string"
},
"enum": [
"A",
"B",
"C",
"D"
],
"enumNames": [
"杭州",
"武汉",
"湖州",
"贵阳"
]
}
}
}
"obj1": {
"title": "可折叠对象",
"description": "这是个对象类型",
"type": "object",
"ui:options": {
"collapsed": true
},
"properties": {
"input1": {
"title": "输入框 1",
"type": "string"
},
"input2": {
"title": "输入框 2",
"type": "string"
}
}
}
{
"type": "object",
"properties": {
"content": {
"title": "富文本编辑器",
"type": "string",
"format": "richText"
}
}
}
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
schame | JSON Schema | object | -- |
formData | 表单的数据 | object | -- |
事件名 | 说明 | 回调函数 |
---|---|---|
on-change | 用户触发表单更新的回调函数 | function(value: formData) |
on-validate | 用户触发表单更新的校验回调函数 | function(value: validates) |
欢迎大家使用并 pr,我们一起打造一款好用的vue form render
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.