vue3单独封装表单校验函数

1.在页面中建一个.ts文件

import { useI18n } from '@/hooks/web/useI18n'
import { FormItemRule } from 'element-plus'

const { t } = useI18n()

interface LengthRange {
  min: number
  max: number
  message?: string
}
//必输项校验
export const useValidator = () => {
  const required = (message?: string): FormItemRule => {
    return {
      required: true,
      message: message || t('common.required')
    }
  }
//长度校验,字符转字节计算,英文字符按 1 字节计算,中文按两个字符
const customByteLengthRange = (options: LengthRange): FormItemRule => {
  const { min, max, message } = options

  return {
    validator: (_, val, callback) => {
      let length = 0
      for (let char of val) {
        if (/[\u4e00-\u9fa5]/.test(char)) {
          length += 2
        } else {
          length += 1
        }
      }

      if (length < min || length > max) {
        callback(new Error(message))
      } else {
        callback()
      }
    }
  }
}

//输入值不能包含空格
  const notSpace = (message?: string): FormItemRule => {
    return {
      validator: (_, val, callback) => {
        if (val?.indexOf(' ') !== -1) {
          callback(new Error(message || t('common.notSpace')))
        } else {
          callback()
        }
      }
    }
  }
//验证输入值不能包含特殊字符
  const notSpecialCharacters = (message?: string): FormItemRule => {
    return {
      validator: (_, val, callback) => {
        if (/[`~!@#$%^&*()_+<>?:"{},.\/;'[\]]/gi.test(val)) {
          callback(new Error(message || t('common.notSpecialCharacters')))
        } else {
          callback()
        }
      }
    }
  }

  return {
    required,
    customByteLengthRange ,
    notSpace,
    notSpecialCharacters
  }
}

2…vue组件内使用方法,useValidator()上面封装的.ts函数

const rules = {
  username: [
    useValidator().customByteLengthRange ({ min: 4, max: 20 }) // 汉字按 2 字节计算,英文字符按 1 字节计算
  ]
}
<think>嗯,用户问的是如何在Vue3中进行表单封装,需要示例教程和最佳实践。首先,我得回忆一下Vue3的特性,比如Composition API和script setup,这些在组件封装中很重要。然后,看看用户提供的引用内容,里面有关于表单请求、组件封装技巧、对话框组件封装和公共组件封装的例子。需要结合这些信息来组织回答。 用户可能是在开发后台管理系统,经常遇到重复的表单需求,所以需要封装表单组件来提高效率。他们可能希望了解如何封装一个可复用的表单组件,如何处理表单验证,如何与父组件通信,以及如何集成请求等。 首先,我需要确定回答的结构。按照用户的要求,结构要清晰,逐步解决问题。可能需要分步骤讲解,比如基础封装验证集成、与父组件通信、请求集成等。每个部分给出代码示例,并引用提供的参考资料中的内容。 比如,引用[3]提到通过属性区分添加和编辑,使用v-if控制表单项,以及调用后端接口。这些都可以在示例中体现。引用[4]中的事件监听,可以用来处理表单提交到父组件。引用[1]和[2]关于封装的目的和技巧,可以强调封装的好处和最佳实践,比如使用v-model、组合式函数、插槽等。 还需要注意用户提到的LaTeX格式要求,但在这个问题中可能用不上,因为主要是前端代码。不过要确保代码块正确使用反引号包裹,并标明语言类型。 可能的问题点:如何传递表单配置,如何处理验证规则,如何与父组件通信,如何集成保存和更新方法。需要一一解答这些,并给出代码示例。例如,使用props传递配置项,利用Vuelidate或Element Plus的验证规则,通过emits触发提交事件,在saveOrUpdate方法中调用API。 另外,最佳实践部分需要总结关键点,比如使用composition API提取逻辑、提供插槽扩展、样式统一等,这些都是用户可能关心的。同时,生成相关问题,引导用户进一步学习,比如性能优化、动态表单生成、第三方库集成等。 最后,检查引用标记是否正确,每个引用是否对应正确的内容。确保回答符合用户的所有要求,特别是结构清晰和真实可靠。</think>### Vue3 表单组件封装教程及最佳实践 --- #### 一、基础表单组件封装 **目标**:创建可复用的表单组件,支持动态配置表单项和双向绑定。 ```vue <!-- FormWrapper.vue --> <template> <el-form :model="formData" label-width="120px"> <el-form-item v-for="(item, index) in formConfig" :key="index" :label="item.label" :prop="item.prop" > <el-input v-if="item.type === &#39;input&#39;" v-model="formData[item.prop]" :placeholder="item.placeholder" /> <el-select v-else-if="item.type === &#39;select&#39;" v-model="formData[item.prop]" :options="item.options" /> </el-form-item> <slot name="footer"></slot> </el-form> </template> <script setup> import { ref, watch } from &#39;vue&#39;; const props = defineProps({ formConfig: { type: Array, required: true }, // 表单项配置 initialData: { type: Object, default: () => ({}) } // 初始数据 }); const emit = defineEmits([&#39;update:modelValue&#39;]); const formData = ref({ ...props.initialData }); // 监听数据变化并同步到父组件 watch(formData, (val) => { emit(&#39;update:modelValue&#39;, val); }, { deep: true }); </script> ``` **使用示例**: ```vue <FormWrapper :form-config="[ { label: &#39;姓名&#39;, prop: &#39;name&#39;, type: &#39;input&#39; }, { label: &#39;角色&#39;, prop: &#39;role&#39;, type: &#39;select&#39;, options: [...] } ]" v-model="formData" /> ``` **关键点**: 1. 通过`formConfig`动态渲染表单项,支持扩展组件类型(如日期选择器)[^3] 2. 使用`v-model`实现父子组件数据双向绑定[^4] --- #### 二、集成表单验证 **最佳实践**:结合`el-form`的校验规则和Vuelidate ```vue <template> <el-form :model="formData" :rules="formRules" ref="formRef"> <!-- 表单项省略 --> </el-form> </template> <script setup> import { computed } from &#39;vue&#39;; import useVuelidate from &#39;@vuelidate/core&#39;; // 生成校验规则 const formRules = computed(() => ({ name: [{ required: true, message: &#39;姓名必填&#39;, trigger: &#39;blur&#39; }], role: [{ validator: (v) => v !== &#39;&#39;, message: &#39;请选择角色&#39; }] })); // 暴露验证方法 defineExpose({ validate: () => formRef.value.validate() }); </script> ``` **引用技巧**:通过`defineExpose`暴露组件方法,父组件可通过`ref`调用验证[^2] --- #### 三、与父组件通信 1. **提交事件处理**: ```vue <!-- 子组件 --> <el-button @click="handleSubmit">提交</el-button> <script setup> const handleSubmit = () => { emit(&#39;submit&#39;, formData.value); }; </script> <!-- 父组件 --> <FormWrapper @submit="handleFormSubmit" /> ``` 2. **通过插槽扩展功能**: ```vue <template #footer> <el-button type="primary">自定义操作</el-button> </template> ``` **引用模式**:事件总线+插槽组合可实现灵活交互 --- #### 四、集成请求方法 **封装保存/更新逻辑**: ```vue <script setup> import { saveData, updateData } from &#39;@/api&#39;; const props = defineProps({ isEdit: { type: Boolean, default: false } // 区分新增/编辑模式[^3] }); const saveOrUpdate = async () => { try { const method = props.isEdit ? updateData : saveData; await method(formData.value); emit(&#39;success&#39;); } catch (err) { console.error(&#39;提交失败:&#39;, err); } }; </script> ``` --- #### 五、最佳实践总结 1. **配置驱动**:将表单结构抽象为JSON配置,便于动态生成[^1] 2. **逻辑复用**:使用Composition API提取`useForm`逻辑 ```js // useForm.js export default (initialData) => { const formData = reactive({ ...initialData }); const resetForm = () => Object.assign(formData, initialData); return { formData, resetForm }; }; ``` 3. **样式统一**:通过SCSS混入统一表单间距、标签宽度等 4. **扩展能力**:提供`<slot>`支持自定义表单项和操作按钮 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值