当前位置: 首页 > news >正文

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后,还得重复写一次,精简的不够极致。而且也无法响应校验的配置变化,算一点小遗憾了,以后有空再继续改造

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【40分钟速成智能风控1】互联网金融风险管理简介
  • 场景文本检测识别学习 day01(传统OCR的流程、常见的损失函数)
  • Qt——Qt实现数据可视化之QChart的使用总结(使用QChart画出动态显示的实时曲线)
  • Layui三级联动插件使用方法
  • 数据结构之栈和队列
  • golang语言系列:Web框架+路由 之 Gin
  • ChatGPT 之优势与缺陷
  • vue3和vue2 之 provide/inject 用法区别 ---vue3组件间通讯2
  • gpt的构造和原理
  • CentOS安装MySQL数据库
  • java操作mongodb详解
  • 汽车CAN网络中的checksum和Rollingcounter的作用?
  • FSQ8罗德与施瓦茨FSQ8信号分析仪
  • 第六题:标题统计
  • 第九届蓝桥杯大赛个人赛省赛(软件类)真题C 语言 A 组-航班时间
  • [Vue CLI 3] 配置解析之 css.extract
  • 【Linux系统编程】快速查找errno错误码信息
  • CentOS7 安装JDK
  • go语言学习初探(一)
  • Java Agent 学习笔记
  • Java 内存分配及垃圾回收机制初探
  • Java方法详解
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • JS实现简单的MVC模式开发小游戏
  • k个最大的数及变种小结
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • nodejs:开发并发布一个nodejs包
  • tensorflow学习笔记3——MNIST应用篇
  • Terraform入门 - 3. 变更基础设施
  • 从0实现一个tiny react(三)生命周期
  • 从输入URL到页面加载发生了什么
  • 回顾 Swift 多平台移植进度 #2
  • 基于组件的设计工作流与界面抽象
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 线性表及其算法(java实现)
  • 详解NodeJs流之一
  • 学习Vue.js的五个小例子
  • 数据可视化之下发图实践
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • #DBA杂记1
  • $(this) 和 this 关键字在 jQuery 中有何不同?
  • $.ajax()方法详解
  • (55)MOS管专题--->(10)MOS管的封装
  • (9)STL算法之逆转旋转
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (Matlab)使用竞争神经网络实现数据聚类
  • (第30天)二叉树阶段总结
  • (九)One-Wire总线-DS18B20
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (学习日记)2024.01.19
  • (转)EOS中账户、钱包和密钥的关系