Elementplus 2.6.1表单校验模块开发体验改进

需求

之前的表单代码看了下,写的比较冗长,于是去万能的Github找点轮子,发现了这个:

GitHub - aweiu/element-ui-verify: 如果你受够了饿了么ElementUI原生的校验方式,那就来试试它吧!一款更懂你的校验插件

但是用起来发现不支持最新的vue,因为里面基于mixin混入。改了一会没耐性了,这么简单个功能,自己卷个轮子算了,索性自己改,但是要有以下几点支持:

1)支持label提示,例如必输的信息,如果前面label为用户的话,输入框提示为“用户昵称不为空”,如果是最小长度检测的话,需要提示“用户昵称最少4字符”。而用户昵称的校验器我只需要设置“用户昵称”这个变量,提示信息自动拼接

2)支持验证器组合,例如同时非空,且为数值格式。

3)支持自定义提示信息,不要自己构造方法,最好都参数化解决

思路

既然都Typescript了,我们就采用对象的方式来解决问题。问题1的方式,只需要在构造器里添加label信息即可。

问题2的方式,写过后端的都知道,有个很舒服的方式叫做 链式调用,OK,把多行代码压缩为一行个的方式就它了。

问题3,给个可选参数就好,这个是es5的好工具,结合typescript的默认值操作很方便的解决

问题4,有些代码直接照搬了github,其它未测试的部分理论上应该没问题,有BUG再回来改😉 

效果

以修改密码的业务为例,这样个界面

改造前

原来代码:

/** 修改密码窗体模块 */
<template><cc-windowref="windowDom"v-bind="$attrs"title="修改当前用户密码"width="400px":append-to-body="true"@submit="onSubmit"><el-formref="editFormDom":model="form"auto-complete="off":label-width="100"class="h-rmargin40":rules="formRules"><el-form-item prop="userPsw" label="输入密码"><el-input type="password" v-model="form.userPsw" maxlength="20" show-password /></el-form-item><el-form-item class="x-fillitem" prop="reUserPsw" label="确认密码"><el-input type="password" v-model="form.reUserPsw" maxlength="20" show-password /></el-form-item></el-form></cc-window>
</template>

校验部分

const formRules = reactive<{userPsw: any[]reUserPsw: any[]
}>({userPsw: [{ required: true, message: '请输入密码', trigger: ['change', 'blur'] },{pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]+\S{5,20}$/,message: '需同时含有字母和数字,长度在6-20之间',trigger: ['change', 'blur']}],reUserPsw: [{ required: true, message: '请重新输入密码', trigger: ['change', 'blur'] },{validator: (rule: any, value: any, callback: object) => {return value === form.userPsw},message: '两次输入的密码不相等',trigger: ['change', 'blur']}]
})

改造后

/** 修改密码窗体模块 */
<template><cc-windowref="windowDom"v-bind="$attrs"title="修改当前用户密码"width="400px":append-to-body="true"@submit="onSubmit"><el-form ref="editFormDom" :model="form" auto-complete="off" :label-width="100" class="h-rmargin40"><el-form-itemprop="userPsw"label="输入密码":rules="utils.validate('密码').required().pattern(/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]+\S{5,20}$/, '需同时含有字母和数字,长度在6-20之间')"><el-input type="password" v-model="form.userPsw" maxlength="20" show-password /></el-form-item><el-form-itemclass="x-fillitem"prop="reUserPsw"label="确认密码":rules="utils.validate('密码').compare(form.userPsw)"><el-input type="password" v-model="form.reUserPsw" maxlength="20" show-password /></el-form-item></el-form></cc-window>
</template>

可见简短了很多,方便使用还避免了出错

代码实现

代码实现也不复杂,写一个模块即可解决:

/*** 链式校验模块,支持常用校验方式** 使用列:* import {validate} from '@/utils/Validator'** //建立一个非空4字符以上的昵称校验,未输入提示“请输入昵称”,过短提示“昵称长度最小为 4 字符”* validate('昵称').required().minLength(4)** 注意除了非空校验外,其它校验都是为空可以通过的,除非显示的指定了非空校验required** @author Jim 24/04/06*/export interface IValidator extends Array<any> {required: (error?: string) => IValidator // 必须输入gt: (value: number, error?: string) => IValidator // 必须大于gte: (value: number, error?: string) => IValidator // 必须大于等于lt: (value: number, error?: string) => IValidator // 必须小于于lte: (value: number, error?: string) => IValidator // 必须小于等于minLength: (size: number, error?: string) => IValidator // 不能小于X字符precision: (digitSize: number, error?: string) => IValidator // 校验数字最大小数位(精度限制)number: () => IValidator // 校验是否为数字int: () => IValidator // 校验是否为整数phone: () => IValidator // 校验是否为手机号(随着号段的增加,未来可能需要更新)email: () => IValidator // 校验是否为电子邮件地址verifyCode: () => IValidator // 校验6位数字验证码pattern: (regex: RegExp, error?: string) => IValidator // 校验正则格式compare: (otherVal: string, error?: string) => Validator // 校验两次输入一致
}export class Validator extends Array implements IValidator {private labelText?: string = undefinedconstructor(label?: string) {super(0)this.labelText = labelreturn this}required(error?: string): Validator {this.push({required: true,message: error ?? (this.labelText ? `请输入${this.labelText}` : '输入不能为空'),trigger: ['change', 'blur']})return this}gt(value: number, error?: string): Validator {this.push({validator: (rule: any, val: any, callback: (error?: Error) => void) => {return !val || val > value},message: error ?? `${this.labelText ?? '输入数值'}应大于 ${value}`,trigger: ['change', 'blur']})return this}gte(value: number, error?: string): Validator {this.push({type: 'number',min: value,transform: (v: string) => Number(v),message: error ?? `${this.labelText ?? '输入数值'}不能小于 ${value}`,trigger: ['change', 'blur']})return this}lt(value: number, error?: string): Validator {this.push({validator: (rule: any, val: any, callback: (error?: Error) => void) => {return !val || val < value},message: error ?? `${this.labelText ?? '输入数值'}应小于 ${value}`,trigger: ['change', 'blur']})return this}lte(value: number, error?: string): Validator {this.push({type: 'number',max: value,transform: (v: string) => Number(v),message: error ?? `${this.labelText ?? '输入数值'}不能大于 ${value}`,trigger: ['change', 'blur']})return this}minLength(size: number, error?: string): Validator {this.push({validator: (rule: any, val: any, callback: (error?: Error) => void) => {return (val?.length || 0) >= size},message: error ?? `${this.labelText ?? '内容'}长度最小为 ${size} 字符`,trigger: ['change', 'blur']})return this}precision(digitSize: number, error?: string): Validator {this.push({validator: (rule: any, val: any, callback: (error?: Error) => void) => {const decimal = val.toString().split('.')[1]return !!decimal && decimal.length < digitSize},message: error ?? `${this.labelText ?? ''}小数部分不能超过 ${digitSize} 位`,trigger: ['change', 'blur']})return this}number(): Validator {return this.pattern(/^([-+])?\d+(\.\d+)?$/, `${this.labelText ?? ''}请输入数字`)}int(): Validator {this.push({type: 'integer',transform: (v: string) => Number(v),message: '请输入整数',trigger: ['change', 'blur']})return this}phone(): Validator {return this.pattern(/^1\d{10}$/, '请输入正确手机号码')}email(): Validator {this.push({type: 'email',message: '邮箱格式不正确',trigger: ['change', 'blur']})return this}verifyCode(): Validator {return this.pattern(/^([-+])?\d+(\.\d+)?$/, '请输入验证码')}compare(otherVal: string, error?: string): Validator {this.push({validator: (rule: any, val: any, callback: (error?: Error) => void) => {return !val || val === otherVal},message: error ?? `${this.labelText ?? ''}两次输入不一致`,trigger: ['change', 'blur']})return this}pattern(regex: RegExp, error?: string) {this.push({validator: (rule: any, val: any, callback: (error?: Error) => void) => {return !val || regex.test(val)},message: error ?? '请输入正确格式',trigger: ['change', 'blur']})return this}
}export const validate: (label?: string) => IValidator = (label) => {return new Validator(label)
}

不到200行搞掂

小遗憾

与element-ui-verify相比,唯一有点小遗憾的这种方式还是基于配置,无法自动获取到label的信息了,不然定义完label后,还得重复写一次,精简的不够极致。而且也无法响应校验的配置变化,算一点小遗憾了,以后有空再继续改造

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/803335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Taro框架中的H5 模板基本搭建

1.H5 模板框架的搭建 一个h5 的基本框架的搭建 基础template 阿乐/H5 Taro 的基础模板

Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️本系列源码仓库&#xff1a;多线程并发编程学习的多个代码片段(github) &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正…

nexus设置s3存储

问题 因为我的nexus是安装在EC2上面&#xff0c;需要利用s3的存储能力&#xff0c;为nexus提供存储服务。 步骤 准备s3桶 输入桶名&#xff0c;创建s3桶&#xff0c;如下图&#xff1a; 创建桶读写策略 具体内容如下&#xff1a; {"Version": "2012-10-1…

c++之代码编译问题

为什么头文件不是编译的对象 1、头文件与包含指令(#include) 那些没有被项目中任何源文件包含的头文件&#xff0c;编译器是不去理会它的&#xff0c;不管它有没有语法错误&#xff0c;也不管它是否已添加到项目中。 2、包含指令的执行 包含指令是一种预编译指令&#xff0c;它…

如何区别进化和演化

在生物学中&#xff0c;"进化"和"演化"这两个词通常可以互换使用&#xff0c;它们都指的是生物种群随时间推移而发生的遗传变化。然而&#xff0c;在某些语境中&#xff0c;这两个词可能会有细微的差别&#xff1a; 进化&#xff08;Evolution&#xff09;…

[翻译] 在 CI 或测试环境中使用 Docker-in-Docker,三思而后行

发布日期&#xff1a;2024-04-08 18:01:01 原文地址&#xff1a;Using Docker-in-Docker for your CI or testing environment? Think twice. Docker-in-Docker 的主要目的是帮助 Docker 本身的开发。许多人使用它来运行 CI&#xff08;例如使用 Jenkins&#xff09;&#xf…

[NKCTF2024]-PWN:leak解析(中国剩余定理泄露libc地址,汇编覆盖返回地址)

查看保护 查看ida 先放exp 完整exp&#xff1a; from pwn import* from sympy.ntheory.modular import crt context(log_leveldebug,archamd64)while True:pprocess(./leak)ps[101,103,107,109,113,127]p.sendafter(bsecret\n,bytes(ps))cs[0]*6for i in range(6):cs[i]u32(p…

Java 基于微信小程序的校园请教小程序的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、10年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447…

SpringBoot整合Spring Data JPA

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉🍎个人主页:Leo的博客💞当前专栏: 循序渐进学SpringBoot ✨特色专栏: MySQL学习 🥭本文内容: SpringBoot整合Spring Data JPA 📚个人知识库: Leo知识库,欢迎大家访问 1.…

淘宝销量API商品详情页原数据APP接口测试㊣

淘宝/天猫获得淘宝app商品详情原数据 API 返回值说明 item_get_app-获得淘宝app商品详情原数据 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地…

Java-StringBuilder容器

一、基础用法 1.创建对象 StringBuilder sbnew StringBuilder(); 2.添加元素 可以添加整型、浮点型、字符串等。 sb.append(1); sb.append(2.3); sb.append(true); 3.反转 sb.reverse(); 4.获取长度 int len sb.length(); 5.转变成字符串 tring strsb.toString(); …

Python学习笔记11 - 列表

1. 列表的创建与删除 2. 列表的查询操作 3. 列表的增、删、改操作 4. 列表元素的排序 5. 列表生成式

利用IP地址判断羊毛用户:IP数据云提供IP风险画像

在当今数字化社会&#xff0c;互联网已经成为人们日常生活和商业活动中不可或缺的一部分。然而&#xff0c;随着网络的普及&#xff0c;网络欺诈行为也日益猖獗&#xff0c;其中包括了羊毛党这一群体。羊毛党指的是利用各种手段获取利益、奖励或者优惠而频繁刷取优惠券、注册账…

png转换成jpg格式?这几种方法很简单

在发送电子邮件时&#xff0c;附件的大小是一个重要的考虑因素。将PNG图像转换为jpg格式可以减小文件大小&#xff0c;减少附件的传输时间和存储空间占用。这对于商务邮件、个人邮件或邮件营销活动中的图片附件都非常有用&#xff0c;下面就介绍几个可以快速完成图片转格式的方…

Docker容器与虚拟化技术:OpenEuler 部署 Prometheus 与 Grafana

目录 一、实验 1.环境 2.OpenEuler 部署 Prometheus 3.OpenEuler 部署 Grafana 4.使用cpolar内网穿透 二、问题 1.拉取镜像失败 2.如何导入Grafana监控模板&#xff08;ES&#xff09; 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统架构版本IP备注…

Scrapy框架spider类异常处理

说明&#xff1a;仅供学习使用&#xff0c;请勿用于非法用途&#xff0c;若有侵权&#xff0c;请联系博主删除 作者&#xff1a;zhu6201976 一、捕获Request所有网络相关异常 在spider类中&#xff0c;我们构造Request对象或FormRequest对象时&#xff0c;可传递参数errback回调…

BugKu:Simple SSTI

1.进入此题 2.查看源代码 可以知道要传入一个名为flag的参数&#xff0c;又说我们经常设置一个secret_key 3.flask模版注入 /?flag{{config.SECRET_KEY}} 4.学有所思 4.1 什么是flask&#xff1f; flask是用python编写的一个轻量web开发框架 4.2 SSTI成因&#xff08;SST…

【数据结构与算法】:堆排序和选择排序

1. 堆排序 堆排序是一种比较复杂的排序算法&#xff0c;因为它的流程比较多&#xff0c;理解起来不会像冒泡排序和选择排序那样直观。 1.1 堆的结构 要理解堆排序&#xff0c;首先要理解堆。堆的逻辑结构是一棵完全二叉树&#xff0c;物理结构是一个数组。 (如果不知道什么是…

链表的中间结点——每日一题

题目链接&#xff1a; OJ链接 题目&#xff1a; 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5] 解释&…

【架构师】-- 成长路线图

成长为软件架构师不是一件容易的事&#xff0c;这篇文章列举了架构师需要学习的技术储备&#xff0c;给出了成为软件架构师的路线图&#xff0c;帮助有志于在架构领域成长的同学可以明确学习的方向。原文&#xff1a;Master Plan for becoming a Software Architect[1] 软件架…