element plus封装表单组件和跨组件的表单校验

最基础的表单组件封装

在做项目的时候,刚开始并没有想到要做表单校验,项目又有超级多的表单要生成,所以最开始想到高度封装一个表单组件,通过参数来生成表单,并进行传值等操作

下面展示了部分代码(远程搜索感觉还挺有意思的,所以保留下来了)


    
      
        
          
        
        
          <减少下代码长度>
        
        
          
            
          
        
        
          <减少下代码长度>
        
        
          <减少下代码长度>
        
        
          <减少下代码长度>
        
      
    
  
import { ref, computed, nextTick } from 'vue'
const props = defineProps({
  data: {
    type: Array,
    required: true,
  },
  Formvalue: {
    type: Object,
    required: true,
  },
})

 这样就完成了一个最简单的封装表单(不包含表单校验),可以通过传递下面的一个数组,生成一个表单

[
  [
    {
      type: 'inputSelect',
      label: '采购计划',
      key: 'purchaseId',
      width: 12,
      remoteFunc: searchFunc('system/purchase-collection/list', 'id'),
      loading: false,
      options: [],
    },
    {
      type: 'input',
      label: '订单金额',
      key: 'amount',
      width: 12,
    },
  ],
  [
    {
      type: 'input',
      label: '单重',
      key: 'singleWeight',
      width: 8,
    },
    {
      type: 'input',
      label: '采购重量',
      key: 'purchaseWeight',
      width: 8,
    },
    {
      type: 'number',
      label: '采购数量',
      key: 'purchaseQuantity',
      width: 8,
    },
  ],
  [
    {
      type: 'textarea',
      label: '备注',
      key: 'remarks',
      width: 24,
    },
  ],
  [
    {
      type: 'fileList',
      label: '发票文件',
      key: 'invoice',
      width: 24,
    },
  ],
]

 element plus封装表单组件和跨组件的表单校验_第1张图片

 远程搜索

感觉这个比较有意思,所以想单独拿出来说,首先searchFunc这个函数有一点点的闭包和柯里化的思想(httpInstance是封装的一个axios),这个函数返回一个函数,利用这个函数作为一个远程搜索的函数,其次再调用返回的函数时,传的参数分别是上面传递的要用于渲染这个form-item的对象(也就是注释中写到的,也就涉及到了第二个点,深拷贝与浅拷贝,也就是我这里的传参,是一个引用传参,所以在这个函数中修改的内容,会同步修改在上文中传递的那个数组,这样就实现了一个远程的联想选择.

const searchFunc = (url, key) => {
  let tempUrl = `${url}?${key}=`
  //ele={
      //type: 'inputSelect',
      //label: '采购计划',
      //key: 'purchaseId',
      //width: 12,
      //rules: [requiredRule],
      //remoteFunc: searchFunc('system/purchase-collection/list', 'id'),
      //loading: false,
      //options: [],
  //}
  return (ele, content) => {
    if (content) {
      ele.loading = true
      console.log(`${tempUrl}${content}`)
      httpInstance({
        url: `${tempUrl}${content}`,
        method: 'get',
        headers: headers,
      }).then((res) => {
        console.log(res)
        ele.options = res.rows.map((item) => {
          return { label: item[key], value: item[key] }
        })
      })
      ele.loading = false
    } else {
      ele.options = []
    }
  }
}

 表单校验

实现跨组件的表单校验,其实原理比较简单,只是逻辑上有点复杂,如果表单只有一个的话,最好的方法是通过pinia来进行状态管理,这里用到的就是父子传参,在适当地使用回调函数callback

HTML不用改很多

//子组件 CreateForm

    <不变的代码>
  

//父组件

JS部分

//父组件
const createFormRef = ref()
//校验,在父组件中传递回调函数,接受子组件中传递出来的valid
createFormRef.value.validateForm((valid) => {
    if (valid) {
        //处理逻辑
    }
})

//清除校验的红色提示
createFormRef.value.clearValidate()

//子组件
import type { FormInstance } from 'element-plus'
const formRef = ref(null)


// 从 data 中提取所有规则
const formRules = computed(() => {
  const rules: Record = {}
  props.data.flat().forEach((ele) => {
    if (ele.rules) {
      rules[ele.key] = ele.rules
    }
  })
  return rules
})
//暴露两个方法给父组件
// 表单校验
const validateForm = (callback: (valid: boolean) => void) => {
  nextTick(() => {
    if (formRef.value) {
      formRef.value.validate((valid: boolean, fields: Record[]) => {
        callback(valid)
      })
    } else {
      callback(false, '表单实例获取失败')
    }
  })
}

//清除校验
const clearValidate = () => {
  if (formRef.value) {
    formRef.value.clearValidate()
  }
}

defineExpose({
  validateForm,
  clearValidate,
})

 传递的参数示例

const requiredRule = { required: true, message: '该字段为必填项', trigger: 'blur' }
const positiveNumberRule = {
  validator: (rule, value, callback) => {
    if (isNaN(Number(value)) || Number(value) <= 0) {
      callback(new Error('请输入大于 0 的数字'))
    } else {
      callback()
    }
  },
  trigger: 'blur',
}


[
  [
    {
      type: 'inputSelect',
      label: '采购计划',
      key: 'purchaseId',
      width: 12,
      rules: [requiredRule],
      remoteFunc: searchFunc('system/purchase-collection/list', 'id'),
      loading: false,
      options: [],
    },
    {
      type: 'input',
      label: '订单金额',
      key: 'amount',
      width: 12,
      rules: [requiredRule,positiveNumberRule],
    },
  ]
]

这样就完成了一个封装程度比较高的表单组件,能够比较简单的使用表单校验

你可能感兴趣的:(vue.js,elementui,javascript)