• vue3 element-puls 表单封装 form封装


    1、前言

    前端最常用的组件表单,每次写表单的时候都要区布局,封装后不要再写布局dom,只需要写一下配置文件即可生成表单。自用封装使用,目前还并不完善,存在一些bug,有需要的小伙伴可以参考,也希望大家评论、点赞!共同学习。

    2、效果图

    在这里插入图片描述

    3、使用展示

    <EZForm label-width="90px"
                label-position="top"
                v-loading="sdata.isLoading"
                :rules="formRules"
                :model="form"
                ref="formRef"
                :settings="formSetting">
          <-- slot 渲染-->
          <template v-slot:permission> 
            <el-tree ref="treeRef" :data="menuTreeData" node-key="value" show-checkbox @check="onPermissionChange"></el-tree>
          </template>
        </EZForm>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
      import {defineComponent, reactive, computed, onBeforeMount, ref, nextTick} from 'vue'
    
      export default defineComponent({
        name: "EditRole",
        setup() {
     
          let menuTreeData = ref([]);
          let treeRef = ref([]);
          const formRef = ref();
          const sdata = reactive({
            visible: false,
            isLoading: false,
            isEdit: false
          });
    
          const form= reactive({
            name:'',
            permission:[],
            desc:'',
            status:1,
          });
    
          const formRules = reactive({
            name:{required:true, message: '请输入', trigger: 'blur'},
            desc:{required:true, message: '请输入', trigger: 'blur'},
            status:{required:true, message: '请选择', trigger: 'change'},
            permission:{required:true, message: '请选择', trigger: 'change'},
          });
    
          const formSetting= reactive({
            formColumn: [
              {component:'el-input',label:'角色名称',key: 'name',attr:{placeholder: '请输入'}},
              {component:'el-radio-group',label:'状态',key: 'status',options:[{label:'正常',value: 1},{label:'禁用',value: 0}]},
              {component:'el-input',label:'角色说明',key: 'desc',attr:{placeholder: '请输入',maxlength:50}},
              {
                component: 'slot',
                label: '角色权限',
                key: 'permission',
              },
            ],
            buttonOptions:{
              okText:'确定',
              cancelText:'取消',
              onOk:()=>{
                sdata.isLoading = true
    
              },
              onCancel: () =>{
                sdata.isLoading  = false;
             
              }
            }
          })
    
       
          return {
            sdata,
            form,
            formRef,
            treeRef,
            formSetting,
            formRules
          };
        }
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    3.1属性

    名称说明类型
    model与element plus 原生属性相同,传入表单对象object
    rules与element plus 原生属性相同,传入表单校验规则object
    settings传入表单配置对象object

    3.1.1 settings属性详解

    const settings = {
    	formColumn:[], //表单项配置
    	buttonOptions:{} // 表单提交按钮 重置按钮
    }
    
    • 1
    • 2
    • 3
    • 4

    3.1.2 fromColumn 详解

    参数类型说明
    componentstringelement puls 表单组件标签名 eg: el-input
    labelstring表单项名称
    keystringv-model绑定
    hiddenboolean切换显示或者隐藏状态,适用于切换类型时候展示不同表单项,默认展示可以不写此参数
    attrobject属性绑定,理论上支持所有属性
    onobject事件绑定 目前支持 click change input select 四个事件,后续完善
    optionsarrayoptions 传入el-select、 el-checkbox-group、el-radio-group选项的数据
    // input
    {
    	component:'el-input', // 表单项组件名称,支持slot
    	label:'角色名称', // 表单项名称
    	key: 'name', // v-model绑定
    	hidden:false, // 切换显示或者隐藏状态,适用于切换类型时候展示不同表单项,默认展示可以不写此参数
    	attr:{placeholder: '请输入'},// 属性绑定
    	on:{ // 事件绑定 目前支持 click change input select 四个事件,后续完善
    		click:()=>{},
    		change:()=>{},
    		input:()=>{},
    		select:()=>{},
    	}
    },
    // select、 checkbox-group、radio-group
    {
    	component:'el-radio-group',
    	label:'状态',
    	key: 'status',
    	options:[{label:'正常',value: 1},{label:'禁用',value: 0}] // options 传入选项数据
    },
    
    // slot
    {
        component: 'slot', // 该项开启slot渲染
        label: '角色权限',
        key: 'permission',
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    3.1.3 buttonOptions

    就这么几个属性没啥好说的了,自己看一下就懂了。

    buttonOptions:{
              okText:'确定',
              cancelText:'取消',
              onOk:()=>{
              },
              onCancel: () =>{
              }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4、源码

    <template>
      <el-form :model="model" :inline="inline" :rules="rules"  :ref="formRef">
        <template v-for="c in settings.formColumn"
                  :key="c.key">
        <el-form-item v-if="!c.hidden"
                      :prop="c.key"
                      :label="c.label"
                      :rules="c.rules"
        >
          <slot v-if="c.component === 'slot'" :name="c.key"></slot>
    
            <component
                v-else
                :is="c.component"
                v-model="model[c.key]"
                :placeholder="c.placeholder"
                v-bind="c.attr"
                @click="c.on&&c.on.click?c.on.click($event):()=>{}"
                @change="c.on&&c.on.change?c.on.change($event):()=>{}"
                @input="c.on&&c.on.input?c.on.input($event):()=>{}"
                @select="c.on&&c.on.select?c.on.select($event):()=>{}"
            >
              <template v-if="c.component === 'el-select'">
                <el-option v-for="op in c.options" :key="op.value" :value="op.value" :label="op.label"></el-option>
              </template>
              <template v-if="c.component === 'el-radio-group' && c.options">
                <el-radio v-for="op in c.options" :key="op.value" :label="op.value">{{op.label}}</el-radio>
              </template>
              <template v-if="c.component === 'el-checkbox-group' && c.options">
                <el-checkbox v-for="op in c.options" :key="op.value" :label="op.value">{{op.label}}</el-checkbox>
              </template>
            </component>
    
        </el-form-item>
        </template>
        <el-form-item>
          <div class="width-full text-align-right">
          <el-button type="primary"
                     v-if="settings.buttonOptions && settings.buttonOptions.okText"
                     @click="onOk">{{settings.buttonOptions.okText}}
          </el-button>
          <el-button @click="onCancel"
                     v-if="settings.buttonOptions && settings.buttonOptions.cancelText"
          >{{settings.buttonOptions.cancelText}}</el-button>
          </div>
        </el-form-item>
      </el-form>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
     import {defineComponent} from 'vue'
    
      const refId = 'formRef-'+ Math.floor(Math.random() * 10000)
      export default defineComponent({
        name: "EZForm",
        props:{
          inline:{
            type: Boolean,
            default: false
          },
          rules:{
            type: Object,
            default: ()=>{}
          },
          model:{
            type: Object,
            default:()=>{},
            required: true
          },
          settings:{
            type: Object,
            default: ()=>{},
            required: true
          }
        },
        data(){
          return{
            formRef: refId
          }
    
        },
        methods: {
          onOk() {
            this.$refs[refId].validate((v) => {
              if (v) {
                this.settings.buttonOptions
                && typeof this.settings.buttonOptions.onOk === "function"
                && this.settings.buttonOptions.onOk();
              }
            })
          },
          resetFields(){
            this.$refs[refId].resetFields()
          },
          onCancel(){
            this.$refs[refId].resetFields()
    
            this.settings.buttonOptions
            && typeof this.settings.buttonOptions.onCancel === "function"
            && this.settings.buttonOptions.onCancel()
          }
        }
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    5、总结

    封装的好处就是可以减少代码编写,提升代码复用率,提升代码质量。
    目前表单并不完善,已知bug:
    1.datepicker 组件在开发模式下正常显示,打包后所有日期都看不见了。
    2.tree组件不能正常使用,传入数据不能渲染
    不过这两都可以通过slot方式进行曲线救国。

    以上就是所有内容了,如果有帮到你,请收藏、点赞、评论!

  • 相关阅读:
    06 C++设计模式之代理(Proxy)模式
    JBoss漏洞之反序列化漏洞
    “转型做 Saas 失败后,我们归档了 5700+Star 的 GitHub 项目!”
    Pytorch(Tensor)-Numpy(ndarrays) API对照表
    【C++ 标准流,文件流】
    跨时钟域(Clock Domain Crossing,CDC)
    Flutter入门教程(二)开发环境搭建
    MFC工控项目实例之十五定时刷新PC6325A模拟量输入
    既然有了malloc/free,C++中为什么还需 要new/delete呢?
    Datawhale-新能源时间序列赛事学习笔记(1)
  • 原文地址:https://blog.csdn.net/wangping146/article/details/125535882