基于 Vue 3.x 的 Form render

github: vue form render

在线演示

简介

我们在写一些常规后台页面的时候,避免不了是需要经常和表单打交道。所以可以想偷懒的小伙伴可能会考虑有没有办法不去做表单工程师?用代码解决重复的人肉工作,没错,我们可以通过 JSON Schema 来描述我们的表单信息,这比重复的写表单控件可方便多了。

但是 JSON Schema 到表单的映射,则是需要我们去关注的,so… 业界有没有比较好的方案呢?答案是肯定的,比如以下几个表单渲染工具:

  • Form Render
  • Formliy

  • 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 功能,后续会不断的维护支持。

使用demo

<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>

Array

  • 支持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

 "string": {
  "title": "字符串",
  "type": "string",
  "maxLength": 4,
  "ui:options": {
    "placeholder": "试着输入超过4个字符"
  }
}

color-picker

 "color": {
  "title": "颜色选择",
  "type": "string",
  "format": "color"
}

date-picker

 "date": {
  "title": "日期选择",
  "type": "string",
  "format": "date"
}

image

"image": {
  "title": "图片展示",
  "type": "string",
  "format": "image"
}

number

"allNumber": {
  "title": "number类",
  "type": "object",
  "properties": {
    "number1": {
      "title": "数字输入框",
      "description": "1 - 1000",
      "type": "number",
      "min": 1,
      "max": 1000
    },
    "number2": {
      "title": "带滑动条",
      "type": "number",
      "ui:widget": "slider"
    }
  }
}

boolean

"allBoolean": {
  "title": "boolean类",
  "type": "object",
  "properties": {
    "radio": {
      "title": "是否通过",
      "type": "boolean"
    },
    "switch": {
      "title": "开关控制",
      "type": "boolean",
      "ui:widget": "switch"
    }
  }
}

date-range

 "allRange": {
  "title": "range类",
  "type": "object",
  "properties": {
    "dateRange": {
      "title": "日期范围",
      "type": "range",
      "format": "dateTime",
      "ui:options": {
        "placeholder": [
          "开始时间",
          "结束时间"
        ]
      }
    }
  }
}

emun

 "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": [
        "杭州",
        "武汉",
        "湖州",
        "贵阳"
      ]
    }
  }
}

Object

"obj1": {
  "title": "可折叠对象",
  "description": "这是个对象类型",
  "type": "object",
  "ui:options": {
    "collapsed": true
  },
  "properties": {
    "input1": {
      "title": "输入框1",
      "type": "string"
    },
    "input2": {
      "title": "输入框2",
      "type": "string"
    }
  }
}

rich-text

{
  "type": "object",
  "properties": {
    "content": {
      "title": "富文本编辑器",
      "type": "string",
      "format": "richText"
    }
  }
}

API

Props

参数说明类型默认值
schameJSON Schemaobject
formData表单的数据object

Events

事件名说明回调函数
on-change用户触发表单更新的回调函数function(value: formData)
on-validate用户触发表单更新的校验回调函数function(value: validates)

最后

欢迎大家使用并pr,我们一起打造一款好用的vue form render

github: vue form render

在线演示

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个报错是因为在渲染过程中,尝试读取了一个空对象或null的属性,导致出现了"TypeError: Cannot read properties of null"的错误信息。根据引用和引用的内容,可以看出这个问题可能出现在两个地方:form对象的checkList字段和state.goodsInfo对象的某个属性。 解决办法可以有两种: 1. 在使用form对象时,确保checkList字段已经定义并且不为null。可以在data函数中初始化form对象,并为checkList字段赋一个空数组的初始值。这样就可以避免报错。具体操作可以参考引用中的代码示例。 2. 在使用state.goodsInfo属性时,确保该属性已经定义并且不为null。可以在getters中,使用短路运算符或逻辑或(||)的方式,在返回值之前对state.goodsInfo进行判断,如果为空对象或null,则返回一个空对象{}作为替代值。这样就可以避免报错。具体操作可以参考引用中的代码示例。 根据具体场景,你可以根据引用和引用中的示例代码,选择适合你的解决办法来避免这个报错。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [2b0e:619 [Vue warn]: Error in render: “TypeError: Cannot read property ‘length](https://blog.csdn.net/bigbigpigsobig/article/details/118961130)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [报错 | vue.runtime.esm....c320:4560 [Vue warn]: Error in render: “TypeError: Cannot read properties of](https://blog.csdn.net/muziqwyk/article/details/126191223)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值