封装组件库-表单(2)

2023, Mar 07    

实现表单的封装

基于Element-plus框架的Form表单组件进行封装。

实现的功能

  • 实现配置型表单,通过json对象的方式自动生成表单
  • 具备更加完备的功能,表单验证,动态删减表单,集成第三方插件(富文本编辑器)
  • 用法更简单,扩展性强(配置项形式),可维护
  • 能够进行弹框嵌套表单等多场景。

初始配置

  • 注册路由组件form,配置为Container组件的子路由组件
  • 采用路由懒加载,箭头函数异步引入组件。
  • 注册通用组件from,为路由组件的子组件,以便组件间通信。
  • 将通用组件form注册为全局组件

实现选择器表单

  • 接口类型定义:关于select、radio、checkbox等选择器组件,内嵌子组件,所以需要定义子组件的接口泛型。 这里对子组件有样式绑定,所以在attrs类型项添加style,需要从vue中引入css的类型。
  import { CSSProperties } from 'vue'
  export interface FormOptions {
    //表单项特有的属性
    attrs?: {
        //css样式
        style?: CSSProperties
    },
    //表单项的子元素
    children?: FormOptions[],
  }

select选择器组件

  • 父组件配置表单数据
  let options: FormOptions[] =[
    {
      type: 'select',
      value: '',
      label: '职位',
      placeholder: '请选择职位',
      prop: 'role',
      attrs: {
        style: {width:'100%'}
      },
      rule:[
        {
          required: true,
          message: '职位不能为空',
          trigger: 'blur'
        }
      ],
      children: [
        {
          type: 'option',
          label: '经理',
          value: '1',
          prop: 'jingli'
        },
        {
          type: 'option',
          label: '主管',
          value: '2',
          prop: 'zhuguan'
        },
        {
          type: 'option',
          label: '员工',
          value: '3',
          prop: 'yuangong'
        }
      ]
    }
  ]
  • 子组件:这里有两种类型,一种为上述用户名、密码的无子组件的输入框组件,另一种为select选择器的含子组件的组件。 所以,将
  <template v-for="(item,index) in options" :key="index">
      <el-form-item :prop="item.prop" :label="item.label" 
        <!-- 显示无子组件的组件 -->
        v-if="!item.children || !item.children.length">
        <component
        v-bind="item.attrs" 
        :is="`el-${item.type}`"
        v-model="model[item.prop]"
        :placeholder="item.placeholder">
        </component>
      </el-form-item>
      <el-form-item
      <!-- 对含children的组件进行渲染 -->
      v-if="item.children && item.children.length"
      :prop='item.prop'
      :label="item.label">
        <component :is="
        `el-${item.type}`"
        :placeholder="item.placeholder"
        v-bind="item.attrs"
        v-model="model[item.prop]">
          <component
          v-for="(child,i) in item.children" :key="i"
          :is="`el-${child.type}`"
          :label="child.label"
          :value="child.value">
          </component>
        </component>
      </el-form-item>
  </template>

checkbox多选框组件

  • 父组件配置表单数据
  {
    type: 'checkbox-group',
    value: [],
    prop: 'aihao',
    label: '爱好',
    rule: [
      {
        required: true,
        message: '爱好不能为空',
        trigger: 'blur'
      }
    ],
    children:[
      {
        type: 'checkbox',
        value: '1',
        prop: 'zuqiu',
        label: '足球'
      },
      {
        type: 'checkbox',
        value: '2',
        prop: 'paiqiu',
        label: '排球'
      },
      {
        type: 'checkbox',
        value: '3',
        prop: 'pingpangqiu',
        label: '乒乓球'
      }
    ]
  }  

radio单选框组件

  {
  type: 'radio-group',
  value: '',
  prop: 'gender',
  label: '性别',
  rule: [
    {
      required: true,
      message: '性别不能为空',
      trigger: 'blur'
    }
  ],
  children:[
    {
      type: 'radio',
      value: 'male',
      prop: 'male',
      label: '男'
    },
    {
      type: 'radio',
      value: 'female',
      prop: 'female',
      label: '女'
    },
    {
      type: 'radio',
      value: 'not',
      prop: 'baomi',
      label: '保密'
    }
  ]
}