基于element-ui组件二次封装篇(3)-form表单2(其他功能开发)

249 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

写在前面的话

本次项目使用到的是vue3.0+ts。上文中封装了form表单的基础功能,实际开发中,表单验证也是极其重要的,当然还有其他个性化开发也要完善。本文就来详细总结一下本人的开发思路。

表单验证

一般开发过程,我们表单都是在<el-form>上添加一个rules规则,然后添加一个个规则进数组中,如果这样开发的话,就是去了封装的意义。实际上我们发现在elementui文档中,每个<el-form-item>都可单独添加一个rules的规则,利用这个,我们便可以完成表单验证的功能的开发。

父组件:给配置项formData数组中给每个表单项添加一个rule规则和是否必选的required字段,和必选后会展示的信息message字段。

如下:

image.png

子组件:

  • 接受每个rule规则,和是否必选的required字段,并使用v-for循环给到每个表单项
  • 提交按钮时,添加表单验证,如表单验证通过,才允许提交

如下:

<el-form ref="ruleFormRef" :model="dialogForm">
    <el-form-item
      v-for="(item, index) in form"
      :key="index"
      :label="item.label"
      :rules="ruleData(item)"
      :prop="item.name"
    >
    <template  v-if="item.type == 'input'">
        <el-input v-model="dialogForm[item.name]"/>
    </template>
   </el-form-item>
    ……
  <el-form-item>
      <el-button type="primary" @click="submitForm(ruleFormRef)">Create</el-button>
   </el-form-item>
</el-form>
 ……
<script lang="ts" setup>
import { ref,toRefs, defineProps,computed,defineEmits  } from "vue";
import type { FormInstance } from 'element-plus'
const props = defineProps({
  form: Array,
  filed:Object,
});
const {form,labelWidth} = toRefs(props);
const dialogForm = computed(() => props.filed);
const ruleFormRef = ref<FormInstance>()
interface Datatemp {
  label:string,
  type:string,
  name:string,
  required?:Boolean,
  message?:string,
  rule?:Array<object>
  option?:Array<object>
}
const TemplateFormat = (data:Datatemp,prop:string) => {
    if(data[prop as keyof Datatemp]&&data[prop as keyof Datatemp]!=null&&data[prop as keyof Datatemp]!=''){
        return data[prop as keyof Datatemp];
    }else{
        if (data.type == "input") {
            return `请输入${data.label}`;
          } else if (data.type == "select") {
            return `请选择${data.label}`;
          }
    }
};
const ruleData = (data:Datatemp)=>{
    let ruleArray=[];
    if(data.required){
        let message=data.message?data.message:TemplateFormat(data,'message')
        let action = data.type=='input'?'blur':'change';
        ruleArray.push({ required: true, message: message, trigger:action})
    }
    if(data.rule&&Array.isArray(data.rule)&&data.rule.length>0){
            ruleArray=[...ruleArray,...data.rule]
    }
    return ruleArray
    
}
​
const emit = defineEmits(['submitVal'])
const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
         emit('submitVal', dialogForm.value);
    } else {
      console.log('error submit!', fields)
    }
  })
}
</script>

大致讲解:ruleData函数中,接收每个项的rules,required,和message

  • 首先判断required是否有值且为true
  • 接着就是判断message,如果有传入message,则按照传入message展示即可,如果没有,则判断input和select不同类型,配置默认的message(在TemplateFormat函数中)。
  • 根据以上两项,在rules数组中添加一项必填的规则
  • 最后根据传入的rules,添加剩下的规则即可。

个性化定制placeholder和labelWidth

  • 个性化定制placeholder

在业务组件传入的配置项placeholder,那么在子组件可根据是否传入placeholder,如果没有,可通过TemplateFormat函数配置默认的placeholder

  • 个性化定制labelWidth

在业务组件传入labelWidth的值,然后在子组件相应配置即可。

子组件代码如下:

image.png

父组件代码如下

image.png

image.png