Vue3+Ts,利用vee-validate封装一个验证表单类似于Elementui el-form

7.2、利用vee-validate封装一个验证表单

文档地址:https://vee-validate.logaretm.com/v4/

整体架构类似于Elmentui的el-Form + el-Form-Item + 表单

一些可能会有疑惑的地方的解释:

  1. 这里的很多属性都利用了透传机制:即父组件身上的属性会透传到子组件的跟组件身上(子组件内必须有唯一一个跟组件才行)
  2. 主要使用作用域插槽来将子组件的数据和方法传递给父组件使用
  3. YuInput是我自己封装的输入框

Validate组件

  1. 该组件结构介绍:
    1. 插槽一slot是默认插槽里面用来放YuValidateItem组件
    2. 插槽二buttonGroup是作用域插槽,默认提供一个提交按钮,并将表单清空的方法提供出去
  2. 功能介绍:
    1. 绑定一个提交的方法,该提交方法触发自定义事件,一旦验证通过会将表单数据提交出去,如果验证失败,点击提交按钮没效果
<template>
  <Form @submit="onSubmit" v-slot="{ resetForm }">
    <slot />
    <slot name="buttonGroup" :resetForm="resetForm">
        <YuButton type="submit" :content="content" />
    </slot>
  </Form>
</template>

<script lang='ts'>
export default {};
</script>
<script setup lang='ts'>
import { Form } from "vee-validate";
import { defineEmits } from "vue";
const props = defineProps({
    content: {
      type: String,
      default: "提交",
    },
  }),
  emit = defineEmits(['onSubmit']),
  onSubmit = (values: any) => {
    emit('onSubmit',values)
  };
</script>


<style lang='scss' scoped>
</style>

validateItem组件

  1. 组件结构介绍:
    1. 插槽一默认插槽,该地方写我们的表单输入框多选框等等。
    2. p标签用来错误提示
  2. 组件功能介绍
    1. 框架本身通过默认插槽提供了一些方法和属性,filed用来绑定表单数据的
    2. errorMessage是表单验证失败的错误提示
    3. 我将框架提供的filed 和 errorMessage向外暴露让父组件可以访问到
<template>
  <Field
    :name="name"
    :rules="(rules as any)"
    #default="{ field, errorMessage }"
    :validate-on-blur="blur"
  >
    
    <slot :field="field" :errorMessage="errorMessage" />
    <p class="text-red-600 text-xs ml-3">{{ errorMessage }}</p>
  </Field>
</template>
<script lang='ts'>
export default {};
</script>
<script setup lang='ts'>
import {  Field, ErrorMessage } from "vee-validate";
const props = defineProps({
  rules: {
    type: [Object,Function],
    default: {},
  },
  name: {
    type: String,
    default: "",
  },
  blur: {
    type: Boolean,
    default: true,
  },
  input: {
    type: Boolean,
    default: false,
  },
});
</script>


<style lang='postcss' scoped>
input {
  @apply w-full;
}
</style>

<登录页面中使用效果展示和代码

  1. 结构介绍
    1. css用的是TailWindCss框架,占篇幅就不贴了
    2. 最外层YuValidate内部必须嵌套YuValidateItem使用,在YuValidateItem内部写我们的表单
  2. 功能介绍
    1. name字符串要和我们绑定的v-model一致,否则提交时无法获取。rules是我们绑定的自定义规则
    2. 输入框等表单需要绑定插槽提供的field
<template>
  <div class="container">
    <div class="login-wrapper">
      <div class="login-form">
        <h1 class="text-center text-gray-700 text-lg">会员登录</h1>
        <YuValidate @onSubmit="onSubmit">
          <YuValidateItem
            name="formData.userName"
            :rules="userNamerules"
            v-slot="{ field, errorMessage }"
            v-model="formData.userName"
          >
            <YuInput
              v-bind="field"
              placeholder="请输入手机号或邮箱"
              type="text"
             
            />
          </YuValidateItem>
          <YuValidateItem
            name="formData.password"
            v-model="formData.password"
            :rules="userPassword"
            v-slot="{ field, errorMessage }"
          >
            <YuInput
              v-bind="field"
              placeholder="请输入密码"
              type="password"
             
            />
          </YuValidateItem>
         
          <template #buttonGroup="{ resetForm }">
            <YuButton type="submit" content="登录" />
            <YuButton  content="清空" @click="resetForm"/>
          </template>
         
        </YuValidate>
        <ul class="login-options">
          <li>网站首页</li>
          <li>会员注册</li>
          <li>找回密码</li>
        </ul>
      </div>
      <div class="login-logo">
        <img src="@/public/images/login-logo.jpg" alt="" />
      </div>
    </div>
  </div>
</template>
<script setup lang='ts'>
import useLogin  from './hooks'
const { formData,userNamerules,userPassword,loginHnadler,onSubmit } = useLogin()


</script>

<hooks

  1. 功能介绍
    1. 该hooks提供与登录表单相关的数据和功能
import useUtils from "../../utils/utils";
import { ref } from "vue";
import * as yup from "yup";
import { useRouter } from "vue-router";
import { loginApi } from "../../api/user";
interface IUserForm {
    userName: string,
    password: string
}
export default function useLogin() {
    const utils = useUtils(),
        formData = ref<IUserForm>({
            userName: "",
            password: "",
        }),
        router = useRouter(),
        userNamerules = utils.Validate.validateEmail,
        userPassword = yup.string().required().min(8),
        loginHnadler = () => {
            loginApi({ userName: "Yu123123", password: "123456" }).then((res) => {
              utils.Storage.set({
                key: "token",
                value: res.data.token,
                expire: "1m",
              });
              router.push("/admin/user");
            });
        },
        onSubmit = (values: any) => {
          console.log(values.formData,);
        };
    return {
        formData,
        userNamerules,
        userPassword,
        loginHnadler,
        onSubmit
    }
}

<邮箱验证的代码

 const validateEmail = (value: string) => {
    // if the field is empty
    if (!value) {
        return '必填项不能为空';
    }
    // if the field is not a valid email
    const regex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
    if (!regex.test(value)) {
        return '格式不正确';
    }
    // All is good
    return true;
}
<还可以优化的地方
  1. 可以直接给Validate传递rules数组来实现验证,弥补现在的问题(表单项多就会增加许多验证规则,从而导致代码不易维护):每个YuValidateItem如果需要验证都必须传递一个rules
    1. 解决方法:最外层YuValidate用一个rules数组来收集规则,数组接受对象,然后传递给YuValidateItem组件,该组件再根据自身需要的rules自行遍历取即可
  2. 样式目前都是写死的,可以通过外部传参动态调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大鲤余

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值