venus_jin-vue-form-creator

vue json form 生成器, 适配element iview

Usage no npm install needed!

<script type="module">
  import venusJinVueFormCreator from 'https://cdn.skypack.dev/venus_jin-vue-form-creator';
</script>

README

vue-form-creator (element ui/ iview适配版本)

  • el-form 在复杂表单上代码量较大
  • 动态校验表单项比较麻烦
  • 表单多字段联动在tempalte 与 js中穿插 代码混乱

解决方案 使用json方案描述表单,对表单数据自动更新,对elment表单控件只做适配(采用jsx透传ui控件属性)

vue-cli 3.0引入jsx写法编译

vue 版本要求 > 2.6.0

npm install @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props -D

修改 babel.config.js/.babelrc

module.exports = {
    presets: [
       ['@vue/app', {
           useBuiltIns: 'entry'
       }],
        ['@vue/babel-preset-jsx',
        {
            "injectH": false
        }]
    ]
}

注意:@vue/babel-preset-jsx默认会注入一个h语法糖,会与vue本身冲突,这个配置要设置false,否则项目启动会报错

form-creator api

参数 说明 类型
v-model 表单值(对应el-form model) object
option el-form 配置透传,除了disabled以外,详见 option object
fields 表单域数组 Array( item 可以是object 或 array )

form-creator 对外暴露一个 getFormRef() 来返回el-form的ref

option api

参数 说明 类型 可选值 默认值
status 代替disabled(boolean) string edit、disabled、 preview edit
debug boolean, 快捷调试入口 boolean - false
autoAuffix el-form-item label 后缀自动补齐(如: '姓名' -> '姓名:') boolean - false
itemSpan formItem span全局参数,优先级itemSpan < formItem.span number 0~24 24

fields item api

参数 说明 类型 可选值 默认值
tag 标签, 与component不同时使用 string - el-input
component 组件,适用于自定义表单控件值 function - -
label label展示值,同下item(label),优先级 label < item.label
name 表单对应字段 string - -
options select checkbox-group时使用 {label: '', value: ''}[]
previewFormItemValue 可选参数,当option.status 为preview时生效,展示文字自定义 - (value, h) => value form[name]
scopedSlots 可选参数,动态slot,必须使用h函数 jsx component[]
on 控件事件透传,在需要做字段联动时使用 object
rules 该字段校验规则,与el-form一致
gutter 可选参数,布局 对应el-row, 只在config item 为Array时配置在Array[0]上
span 可选参数,布局 对应el-col
item 对应el-form-item 属性透传,(prop 对应 name, 不需要再声明prop) object {label: ''}
在component/scopedSlots中 组件书写方式
  • component: import 过来以.vue结尾的,以jsx functional component 实现的,直接写变量;
  • scopedSlots: 要以jsx形式书写 h => jsx component
example
  • 全局引入
import VueFormCreator from '@yowant/vue-form-creator'
Vue.use(VueFormCreator, 'iview')// 第二个人参数传 'iview' 或 'element'
<template>
<FormCreator 
  v-model="formData"
  :option="options"
  :fields="formConfig"
/>
</template>

<script>


export default {
    data() {
        return {
            options: {
                'label-width': '100px',
                inline: false,
                status: 'edit', // 表单状态 edit disabled preview
                debug: process.env.NODE_ENV === 'development',
            },
            formData: {
                title: '标题',
                age: null,
                selectVal: ['1', '2'],
                goods: [
                    { id: '', name: '2' },
                ],
            }
        }
    },
    computed: {
        formConfig() {
            return [
                {
                    item: {// el-form-item
                        label: '标题',
                        style: { // 自定义style
                            'border-bottom': '1px solid red',
                        },
                        class: '', // 自定义class
                    },
                    tag: 'el-input',
                    name: 'title',
                    span: 12, // 布局 el-col 对应的span   
                },
                {
                    label: '年龄',
                    item: {
                        label: '展示年龄', // 优先级高于label
                    },
                    tag: 'el-input-input',
                    name: 'age',
                    span: 12, // 布局 el-col 对应的span   
                },
                {
                  tag: 'el-select',
                  span: 14,
                  item: {
                    label: 'select',
                    scopedSlots: [
                      h => (<span>元</span>),
                    ],
                  },
                  name: 'selectVal',
                  clearable: true,
                  multiple: true,
                  options: [
                    { label: '下拉1', value: '1' },
                    { label: '下拉2', value: '2' },
                    { label: '下拉3', value: '3' },
                  ],
                  on: {
                    change: this.selectValChange
                  },
                  scopedSlots: [
                  ]
                },
                ...this.getGoods(), // 注意这里是一个数组 数组每一项在一个row里,主要是为了做布局
                
            ]
        }
    },
    methods() {
        getGoods() {
          const goodItem = (i) => [
            {
              tag: 'el-input',
              suffixIcon: 'el-icon-date',
              gutter: 10, // gutter 必须在数组第一个
              span: 4,
              item: {
                label: `goodid ${i}`,
              },
              name: `goods[${i}].id`,
              on: {
                change: this.titleChange
              },
              rules: [
                { required: true, message: '请输入编号' }
              ]
            },
            {
              // tag: 'el-input',
              span: 8,
              item: {
                label: `goodname ${i}`,
              },
              name: `goods[${i}].name`,
              on: {
                change: this.titleChange
              },
              rules: [
                { required: true, message: '请输入name' }
              ]
            },
            {
              component: (h) => (
                <span>
                  <el-button type="primary" icon="el-icon-plus" circle onClick={this.addGood} ></el-button>
                  <el-button type="danger" icon="el-icon-minus" circle onClick={() => this.minus(i)}></el-button>
                </span>
              )
            }
          ]
    
          return this.formData.goods.map((ele, i) => goodItem(i))
        },
        selectValChange(value) {
            console.log('slelect回调', value)  
        },
        submit() {
          this.$refs.formbuild.getFormRef().validate(valid => {
            console.log(valid)
          })
        },
    },
}

</script>

注意 表单fields 不要放在data里, computed 里可以自动关联this、依赖更新响应

一个带有校验、布局配置的复杂form实现了

  • 编辑状态(edit)

edit

  • 禁用状态(disabled)

image

  • 预览状态(preview)

image

  • iview 版本demo

image 项目代码示例 element

http://gitlab.ywwl.com/H5/xiaoy-zhibo-saas/blob/formcreate/src/views/Demo/FormBuild.vue

iview

http://gitlab.ywwl.com/yfe/vue-form-creator/blob/master/src/components/FormDemo.vue

项目内网git地址http://gitlab.ywwl.com/yfe/vue-form-creator