# RocketForm

动态表单组件,基于 JSON 动态生成常规表单,用法可参考,目前支持。

# 支持功能

基本涵盖所有 ElementUI 表单组件,详情请参考 RocketUI 文档

# 基本用法

长度最大6位
至少选择一项
<rocket-form
  ref="rocketForm"
  :json="dialogConfig"
  v-model="rocketForm"
  @handleSubmit="handleSubmit"
  @handleClose="handleClose"
></rocket-form>
<script>
  export default {
    data() {
      return {
        dialogConfig: {
          showFooter: true,
          layout: {
            gutter: 15,
          },
          formList: [
            {
              type: 'text',
              label: '用户名称',
              placeholder: '请输入用户名称',
              model: 'cname',
              required: true,
              width: '80%',
              tips: {
                align: 'right',
                text: '长度最大6位',
              },
              rules: [
                {
                  required: true,
                  message: '请输入用户名称',
                  trigger: ['change', 'blur'],
                },
                {
                  pattern: /^[a-zA-Z0-9_\u4e00-\u9fa5]{1,10}$/,
                  message: '1-10个字符,支持中文、字母、数字和下划线',
                  trigger: ['change', 'blur'],
                },
              ],
            },
            {
              type: 'select',
              label: '用户状态',
              placeholder: '请选择用户状态',
              model: 'user_status',
              tips: '至少选择一项',
              options: [
                { label: '已注销', value: 1 },
                { label: '老用户', value: 2 },
                { label: '新用户', value: 3 },
              ],
            },
            {
              type: 'inline',
              label: '城市',
              list: [
                {
                  type: 'select',
                  placeholder: '请选择省份',
                  model: 'user_province',
                  change: this.getSelectList,
                  options: [
                    {
                      label: '湖北省',
                      value: 10001,
                    },
                    {
                      label: '上海市',
                      value: 20001,
                    },
                  ],
                },
                {
                  type: 'select',
                  placeholder: '请选择城市',
                  model: 'user_city',
                  options: [
                    {
                      label: '武汉市',
                      value: 10001,
                    },
                    {
                      label: '上海市',
                      value: 20001,
                    },
                  ],
                },
              ],
            },
            {
              type: 'radio',
              label: '使用状态',
              placeholder: '请选择使用状态',
              model: 'use_status',
              options: [
                { label: '在线', value: 1 },
                { label: '离线', value: 2 },
              ],
            },
            {
              type: 'switch',
              label: '启用状态',
              model: 'status',
            },
            {
              type: 'date',
              label: '注册日期',
              model: 'register_date',
              shortcuts: true,
            },
            {
              type: 'checkbox',
              label: '兴趣',
              model: 'intrest',
              options: [
                { label: '游泳', value: 1 },
                { label: '打乒乓球', value: 2 },
                { label: '台球', value: 3 },
                { label: '篮球', value: 4 },
              ],
            },
            {
              type: 'textarea',
              label: '用户描述',
              placeholder: '请输入用户描述',
              model: 'remark',
              rows: 4,
            },
          ],
        },
        // v-model对象,可初始化值
        rocketForm: {
          cname: 'jack',
          intrest: [1, 2],
        },
      };
    },
    methods: {
      async handleSubmit() {
        const res = await this.$request.get('/user/submit', this.rocketForm);
        if (res) {
          this.$message.success('操作成功');
          // 如果需要,可对表单进行重置
          this.$refs['rocketForm'].handleReset();
          // 关闭页面
          this.handleClose();
        }
      },
      getSelectList(val, values, model) {
        this.$request.get('/select/list').then((res) => {
          this.dialogConfig.formList[2].list[1].options = res;
        });
      },
      handleClose() {
        this.$message.success('关闭页面');
      },
    },
  };
</script>
Expand Copy

# 嵌套表单用法

长度最大6位
%
普通文本
<rocket-form
  :json="dialogConfig"
  v-model="rocketForm"
  @handleSubmit="handleSubmit"
  @handleClose="handleClose"
></rocket-form>
<script>
  export default {
    data() {
      return {
        dialogConfig: {
          showFooter: true,
          layout: {
            gutter: 15,
          },
          formList: [
            {
              type: 'text',
              label: '用户名称',
              placeholder: '请输入用户名称',
              model: 'cname',
              required: true,
              width: '80%',
              tips: {
                align: 'right',
                text: '长度最大6位',
              },
              rules: [
                {
                  required: true,
                  message: '请输入用户名称',
                  trigger: ['change', 'blur'],
                },
                {
                  pattern: /^[a-zA-Z0-9_\u4e00-\u9fa5]{1,10}$/,
                  message: '1-10个字符,支持中文、字母、数字和下划线',
                  trigger: ['change', 'blur'],
                },
              ],
            },
            {
              type: 'inline',
              label: '下拉组合',
              list: [
                {
                  type: 'select',
                  placeholder: '请选择省份',
                  model: 'user_province',
                  change: this.getSelectList,
                  options: [
                    {
                      label: '湖北省',
                      value: 10001,
                    },
                    {
                      label: '上海市',
                      value: 20001,
                    },
                  ],
                },
                {
                  type: 'select',
                  placeholder: '请选择城市',
                  model: 'user_city',
                  options: [
                    {
                      label: '武汉市',
                      value: 10001,
                    },
                    {
                      label: '上海市',
                      value: 20001,
                    },
                  ],
                },
              ],
            },
            {
              type: 'inline',
              label: '随意组合',
              list: [
                {
                  type: 'radio',
                  label: '',
                  placeholder: '请选择使用状态',
                  model: 'use_status',
                  options: [
                    { label: '在线', value: 1 },
                    { label: '离线', value: 2 },
                  ],
                },
                {
                  type: 'switch',
                  label: '启用状态',
                  model: 'status',
                },
              ],
            },
            {
              type: 'inline',
              label: '概率配置',
              list: [
                {
                  span: 8,
                  type: 'select',
                  placeholder: '请选择概率配置',
                  model: 'a3',
                  labelWidth: '0',
                  options: [
                    { label: '10%', value: 1 },
                    { label: '20%', value: 2 },
                    { label: '30%', value: 3 },
                    { label: '40%', value: 4 },
                  ],
                },
                {
                  span: 8,
                  type: 'input',
                  placeholder: '请输入概率配置',
                  model: 'a4',
                  append: '%',
                  labelWidth: '0',
                },
                {
                  span: 3,
                  type: 'button',
                  button: {
                    type: 'text',
                    text: '按钮',
                  },
                  labelWidth: '0',
                },
                {
                  span: 5,
                  type: 'label',
                  text: '普通文本',
                },
              ],
            },
            {
              type: 'group',
              label: '分组 - 组合',
              list: [
                [
                  {
                    span: 8,
                    type: 'input',
                    placeholder: '请输入抽取次数',
                    label: '抽取',
                    labelWidth: '80px',
                    model: 'a7',
                    rules: [
                      {
                        required: true,
                        message: '请输入抽取次数',
                        trigger: 'blur',
                      },
                    ],
                    label1: '次可开启宝箱1',
                  },
                  {
                    span: 8,
                    type: 'input',
                    placeholder: '请输入奖励金币',
                    label: '奖励金币',
                    model: 'a8',
                    rules: [
                      {
                        required: true,
                        message: '请输入奖励金币',
                        trigger: 'blur',
                      },
                    ],
                  },
                  {
                    span: 3,
                    type: 'button',
                    button: {
                      type: 'primary',
                      round: true,
                      icon: 'el-icon-plus',
                      text: '按钮',
                    },
                    click(value, config) {
                      // 可监听点击事件
                      console.log(value, config);
                    },
                    labelWidth: '0',
                  },
                ],
              ],
            },
          ],
        },
        // v-model对象,可初始化值
        rocketForm: {
          cname: 'jack',
          intrest: [1, 2],
        },
      };
    },
    methods: {
      async handleSubmit() {
        const res = await this.$request.get('/user/submit', this.rocketForm);
        if (res) {
          this.$message.success('操作成功');
          // 如果需要,可对表单进行重置
          this.$refs['rocketForm'].handleReset();
          // 关闭页面
          this.handleClose();
        }
      },
      getSelectList(val, values, model) {
        this.$request.get('/select/list').then((res) => {
          this.dialogConfig.formList[2].list[1].options = res;
        });
      },
      handleClose() {
        this.$message.success('关闭页面');
      },
    },
  };
</script>
Expand Copy

# 弹框表单,包含组件关联显示隐藏

可嵌套在 dialog 中使用,所有组件的用法跟 QueryForm 一样,可通过 show 对象来做关联显示

<el-button type="primary" @click="showModal=true">弹框表单</el-button>
<el-dialog
  title="用户信息"
  :visible.sync="showModal"
  width="50%"
  @close="handleClose"
>
  <rocket-form
    ref="dialogForm"
    :json="dialogConfig"
    v-model="dialogForm"
    @handleSubmit="handleSubmit"
    @handleClose="handleClose"
  ></rocket-form>
  <span slot="footer">
    <el-button @click="handleClose">取 消</el-button>
    <el-button type="primary" @click="handleSubmit">确 定</el-button>
  </span>
</el-dialog>
<script>
  export default {
    data() {
      return {
        showModal: false,
        dialogForm: {
          intrest: [1],
        }, //初始化表单
        dialogConfig: {
          formWidth: '700px', // 表单宽度,默认100%
          labelWidth: '100px', // 左侧文本宽度,默认100px
          size: 'medium', // 表单控件大小,默认medium
          labelSuffix: ':', // 文本后缀,默认 冒号
          showFooter: false, // 是否显示默认的提交按钮,弹框组件里面也有确定和取消,可二选一
          formList: [
            {
              type: 'text', // 文本框
              label: '用户名称',
              placeholder: '请输入用户名称',
              model: 'cname',
              maxlength: '10',
              showWordLimit: true,
              prepend: 'https://', // 前缀
              append: '.com', // 后缀
              prefixIcon: 'el-icon-search', //前缀icon
              change(val, values, model) {
                // 可获取所有值,也可直接重置修改其它字段
                values.query_field = 2;
              },
              required: true, // 必填,会在文本前加*
              tips: '用户名长度最少6个', // 文本框下提示语
              rules: [
                // 规则
                {
                  required: true,
                  message: '请输入用户名称',
                  trigger: ['change', 'blur'],
                },
                {
                  pattern: /^[a-zA-Z0-9_\u4e00-\u9fa5]{1,10}$/,
                  message: '1-10个字符,支持中文、字母、数字和下划线',
                  trigger: ['change', 'blur'],
                },
              ],
            },
            {
              type: 'select', // 下拉框
              label: '用户状态',
              placeholder: '请选择用户状态',
              model: 'user_status',
              options: [
                { label: '已注销', value: 1 },
                { label: '老用户', value: 2 },
                { label: '新用户', value: 3 },
              ],
            },
            {
              type: 'radio', // 单选
              label: '使用状态',
              placeholder: '请选择使用状态',
              model: 'use_status',
              options: [
                { label: '在线', value: 1 },
                { label: '离线', value: 2 },
              ],
            },
            {
              type: 'radiogroup', // 单选 - 按钮组合
              label: '类型',
              model: 'user_type',
              action: {
                type: 'reset', // 当切换按钮组时,会重置对应字段
                model: 'all', // 重置所有表单,也可通过数组重置部分表单
                // model: ['status', 'register_date', 'register_date_range']
              },
              options: [
                {
                  value: 1,
                  label: '少年',
                },
                {
                  value: 2,
                  label: '青年',
                },
                {
                  value: 3,
                  label: '中年',
                },
                {
                  value: 4,
                  label: '老年',
                },
              ],
            },
            {
              type: 'switch', // 开关
              label: '启用状态',
              model: 'status',
              activeValue: 1, // 默认打开,值为true,可修改为1
              inactiveValue: 0, // 默认关闭,值为false,可修改为0
              show: {
                // 当user_type为 1/3/4 时,才显示
                model: 'user_type',
                val: [1, 3, 4],
              },
              // 或者
              show: (form) => {
                return [1, 3, 4].includes(form.user_type);
              },
            },
            {
              type: 'checkbox',
              label: '兴趣',
              model: 'intrest',
              options: [
                { label: '游泳', value: 1 },
                { label: '打乒乓球', value: 2 },
                { label: '台球', value: 3 },
                { label: '篮球', value: 4 },
              ],
              show: {
                // 当user_type为 1/3/4 时,才显示
                model: 'user_type',
                val: [1],
              },
              // 或者
              show: (form) => {
                return form.user_type == 1;
              },
            },
          ],
        },
      };
    },
    methods: {
      async handleSubmit() {
        const res = await this.$request.get('/user/submit', this.rocketForm);
        if (res) {
          this.$message.success('操作成功');
          // 如果需要,可对表单进行重置
          this.$refs['rocketForm'].handleReset();
          // 关闭页面
          this.handleClose();
        }
      },
      getSelectList(val, values, model) {
        this.$request.get('/select/list').then((res) => {
          this.dialogConfig.formList[2].items[1].options = res;
        });
      },
      handleClose() {
        this.$message.success('关闭页面');
        this.showModal = false;
      },
    },
  };
</script>
Expand Copy
  1. 示例中的属性比较多,但实际开发的过程中,属性是很少的,文档是为了让大家知道都有哪些属性可以配置,所以整理的比较全。
  2. 表单联动、表单事件基本都是满足的,表单的显示和隐藏使用 show 来配置,如果 JSON 配置不出来,show 可以直接定义函数来实现。

# JSON 配置 - 上传

<el-button type="primary" @click="showModal=true">弹框表单 - 上传</el-button>
<el-dialog title="用户信息" :visible.sync="showModal" width="50%">
  <rocket-form
    ref="dialogForm"
    :json="dialogConfig"
    v-model="dialogForm"
  ></rocket-form>
  <span slot="footer">
    <el-button @click="showModal=false">取 消</el-button>
    <el-button type="primary">确 定</el-button>
  </span>
</el-dialog>
<script>
  export default {
    data() {
      return {
        showModal: false,
        dialogForm: {},
        dialogConfig: {
          labelWidth: '150',
          formList: [
            {
              type: 'upload',
              label: '普通上传-text',
              model: 'user_image',
              listType: 'text', //展示类型:text/picture/picture-card
              action: '/mock/437/upload', //上传接口
              token: '', //如果接口需要token,就设置一下
              fileType: ['image/jpg', 'image/jpeg', 'image/png'], //文件格式校验
              fileSize: 1 * 1024, //校验大小,单位为K
              limit: 3, //上传个数限制
              multiple: false, // 单个上传活批量上传
              tips: '只能上传jpg/png文件,且不超过500kb', //上传提示语
              response: {
                response: '',
                code: 'code',
                data: 'data',
                msg: 'msg',
                codeVal: 0,
                dataVal: 'url',
              }, //设置返回数据结构,每个接口定义可能不同
            },
            {
              type: 'upload',
              label: '列表上传-card',
              model: 'user_image',
              listType: 'picture-card', //展示类型:text/picture/picture-card
              action: '/mock/437/upload', //上传接口
              token: '', //如果接口需要token,就设置一下
              fileType: ['image/jpg', 'image/jpeg', 'image/png'], //文件格式校验
              fileSize: 1 * 1024, //校验大小,单位为K
              limit: 3, //上传个数限制
              fileLimit: {
                width: 200,
                height: 300,
                // 或者可以设置ratio,宽高比,但是它于宽度属性是互斥的
                // ratio: 1
                tips: '图片尺寸不符合要求',
              },
              multiple: false, // 单个上传活批量上传
              tips: '只能上传jpg/png文件,且不超过500kb', //上传提示语
              response: {
                response: '',
                code: 'code',
                data: 'data',
                msg: 'msg',
                codeVal: 0,
                dataVal: 'url',
              }, //设置返回数据结构,每个接口定义可能不同
            },
            {
              type: 'upload',
              label: '列表上传-picture',
              model: 'user_image',
              listType: 'picture', //展示类型:text/picture/picture-card
              action: '/mock/437/upload', //上传接口
              token: '', //如果接口需要token,就设置一下
              fileType: ['image/jpg', 'image/jpeg', 'image/png'], //文件格式校验
              fileSize: 1 * 1024, //校验大小,单位为K
              limit: 3, //上传个数限制
              multiple: false, // 单个上传活批量上传
              tips: '只能上传jpg/png文件,且不超过500kb', //上传提示语
              //设置返回数据结构,每个接口定义可能不同
              response: {
                code: 'code',
                data: 'data',
                msg: 'msg',
                codeVal: 0,
                dataVal: 'url',
              },
            },
          ],
        },
      };
    },
  };
</script>
Expand Copy

# JSON 配置 - 穿梭框

<el-button type="primary" @click="showModal=true">穿梭框</el-button>
<el-dialog title="用户信息" :visible.sync="showModal" width="50%">
  <rocket-form
    ref="dialogForm"
    :json="dialogConfig"
    v-model="dialogForm"
  ></rocket-form>
  <span slot="footer">
    <el-button @click="showModal=false">取 消</el-button>
    <el-button type="primary">确 定</el-button>
  </span>
</el-dialog>
<script>
  export default {
    data() {
      return {
        showModal: false,
        dialogForm: {},
        dialogConfig: {
          formList: [
            {
              type: 'transfer',
              label: '授权用户',
              model: 'checkedUser',
              filterable: true,
              placeholder: '请选择授权用户',
              titles: ['未授权用户', '已授权用户'],
              buttonTexts: ['回左边', '到右边'],
              leftDefaultChecked: ['4'],
              rightDefaultChecked: ['3'],
              data: [
                {
                  key: '1',
                  label: 'Jack',
                  disabled: true,
                },
                {
                  key: '2',
                  label: 'Tom',
                },
                {
                  key: '3',
                  label: 'Lucy',
                },
                {
                  key: '4',
                  label: 'Lily',
                },
              ],
            },
          ],
        },
      };
    },
  };
</script>
Expand Copy

# JSON 配置 - 嵌套表格

共 0 条
  • 1
前往
<rocket-form :json="json" v-model="form" />

<script>
  export default {
    data() {
      return {
        form: {
          userName: '', //初始化值
          userList: [
            { name: 'jack', age: 20 },
            { name: 'tom', age: 30 },
          ], //初始化值
        },
        json: {
          formList: [
            {
              type: 'text',
              label: '用户名',
              model: 'userName',
            },
            {
              type: 'table',
              label: '用户信息',
              model: 'userList',
              table: {
                border: true,
                handleAction() {
                  // 接受操作按钮点击
                },
                handleCellClick() {
                  // 接受单元格点击
                },
                handleChange() {
                  // 接受页码切换事件
                },
                selectionChange() {
                  // 接受复选事件(表格中有复选框列)
                },
                sortChange() {
                  // 排序事件
                },
                column: [
                  {
                    prop: 'name',
                    label: '用户名',
                  },
                  {
                    prop: 'age',
                    label: '年龄',
                  },
                ],
              },
            },
          ],
        },
      };
    },
  };
</script>
Expand Copy

# JSON 配置 - 支持插槽开发

<rocket-form :json="json" v-model="form">
  <template v-slot:userAge>
    <el-input v-model="form.age" />
  </template>
</rocket-form>

<script>
  export default {
    data() {
      return {
        form: {
          userName: '',
          age: 10,
        },
        json: {
          formList: [
            {
              type: 'text',
              label: '用户名',
              model: 'userName',
            },
            {
              type: 'slot',
              label: '年龄',
              model: 'age',
              slotName: 'userAge',
            },
          ],
        },
      };
    },
  };
</script>
Expand Copy

# RocketForm 属性

参数 说明 类型 可选值 默认值
ref 同 Vue 原生用法 String - 撑满全屏
config 动态表单配置 String - -
v-model 响应式对象 String - -
@handleClose 关闭按钮 fn 参考下文
@handleSubmit 提交按钮 fn 参考下文

# config 参数

参数 说明 类型 可选值 默认值
formWidth 表单宽度 String 700px 撑满全屏
labelWidth 表单文本宽度 String 100px 100px
labelSuffix 文本后缀 String : :
size 表单控件大小 String medium | small | mini medium
formList 渲染表单数组 Array 参考下文
showFooter 显示默认提交按钮 Boolean true | false false
btnGroup 确定/取消自定义配置 Object 参考下文
layout 布局配置 Object 参考 ElementUI 布局
rules 表单验证,同 elementUI Object 参考 ElementUI

layout 目前主要用于 gutter,formList 中的控件默认都是 el-row+el-col 布局,所以可以设置间隙

# 组件内通用配置

参数 说明 类型 可选值 默认值
width 会设置到 style 里面去 String
style 会生成 style 属性 Object

如果 input 或其它控件只配置了 width,则源码会通过style={width:${width}}进行拼接 如果 input 或其它控件只配置了 style,则源码会通过style=${style}进行设置

# type - label

参数 说明 类型 可选值 默认值
type 渲染类型 String label
text 渲染值,动态值可通过 v-model 控制 String

# type - tips

参数 说明 类型 可选值 默认值
type 渲染类型 String tips
tips 渲染内容 String Object

tips 默认在组件下方 {type:'tips',tips:'test'} tips 在组件右方 {type:'tips',tips:{align:'right',text:'test'}

tips 设置在组件下方 {type:'tips',tips:{align:'bottom',text:'test'}

# type - button

参数 说明 类型 可选值 默认值
type 渲染按钮 String button
button 按钮配置 Object 跟 ElementUI 保持一致

{type:'button',button:{type:'primary',icon='el-icon-edit',text:'按钮'}}

# config - btnGroup

参数 说明 类型 可选值 默认值
confirm 确认按钮配置 Object { text:'确认',loading:true }
cancel 取消按钮配置 Object { text:'取消' }

# type - upload

参数 说明 类型 可选值 默认值
type 文件上传 String 参考标题
listType 列表类型 String text/picture/picture-card picture-card
action 上传接口地址 String
token 上传 token,可选 String
fileType 限制文件类型 Array ["image/jpg"]
fileSize 限制文件大小 Number 1*1024 单位 K
limit 限制文件个数 Number 1....n
fileLimit 限制文件尺寸 Number {width:300,height:300,ratio:1}
name 修改 file 的 name 值 String fileKey
data 附带参数 Any
response 设置接口结构 Object 默认:code,data,msg
httpRequest 自定义上传 Object 默认:code,data,msg

fileLimit 中,宽度和高度属性与 ratio 是互斥,ratio 是限制图片上传宽高比例

# upload - response 返回结构设置

参数 说明 类型 可选值 默认值
response 返回对象 String
code 设置 code 结构 String
data 设置 data 结构 String
msg 设置错误结构 String
codeVal 设置成功返回值 String

假设上传接口返回 {code:0,data:{url:'http://xxx.jpg'},msg:''},这种就是标准的数据结构,我们不需要设置response,如果接口返回:{result:{status:200,data:{url:'http://xxx.jpg'},msg:''}},则我们需要设置response,来保证上传组件可以接收正确的值

/**
 * 如果接口返回如下结构,则我们需要单独设置响应体
 * {result:{status:200,data:{url:'http://xxx.jpg'},msg:''}}
*/
{
    type: 'upload',
    response:{
        response: 'result',
        code: 'status',
        data: 'data',
        msg: 'msg',
        codeVal: 200
    }
}

# type - transfer

参数 说明 类型 可选值 默认值
type 穿梭框 String 参考标题
filterable 是否过滤 Boolean true/false false
titles 两个标题 Array 可不填
buttonTexts 按钮文本 Array 可不填
leftDefaultChecked 左侧选中得值 Array 可不填
rightDefaultChecked 右侧选中得值 Array 可不填
data 数据源 Array {key,label,disabled}

# 事件处理

参数 说明 类型 可选值 默认值
@handleClose 取消事件 fn 参考示例
@handleSubmit 确定事件 fn 参考示例

# API 方法

参数 说明 类型 可选值 默认值
handleReset 通过 ref 调用,可重置表单 fn 参考示例
validate 自定义表单校验,通过 ref 调用,回调参数为 el-ui 表单校验结果 Promise/fn