微信小程序实现表单校验功能

发布时间 - 2026-01-11 02:57:53    点击率:

小程序SDK版本 1.4

表单校验之难

如果要问微信小程序最难实现的公共业务是什么?应该是表单校验,没有之一。原因如下:

表单组件在数量上达到11个,居各类组件之首。当然幸运的是,并不是所有的都需要校验。
而这些组件操作方式多样,可分为滑动、(多行)输入、点击、点击+滑动。
即使是同一个组件,因为业务场景不同就会有不同的校验规则。
更麻烦的是,这些组件之间经常还会联动或者关联校验。

但是,作为一个非简单静态页面,有着较多用户交互的小程序,表单校验又是一个非常常用的功能:登录、注册、新增、编辑…

总而言之:表单组件的多样性 X 校验规则的多样性 = 复杂的公共业务

这么棘手的问题我们怎么来解决它呢?

尝试组件化

如果你关注近年前端发展趋势,一定会想到“组件化”来实现:

把每个表单组件的视图、样式、校验逻辑封装成单独的业务组件,然后直接调用。

可事情似乎没这么简单。

如果考虑把n个原生组件抽象出来,配上n个校验规则,再乘以组件之间的关系n(的全排列),复杂度至少达到n³。

而且每个组件的校验失败或成功都要通知父组件,以便显示错误信息或者进行下一步操作。

这样不但没有解决问题,反而使得这些公用的表单组件过于复杂,耦合混乱。

尝试非组件化

既然原先的思路行不通,再来回到出发点,看看我们最核心的需要被抽象出来的是什么。

无非是两样东西:视图层的元素样式和逻辑层的校验规则。

上面说到封装原生表单组件会极大的增加复杂度,索性放弃它,复杂度瞬间可以下降到n²。

但同时我们又要保持样式统一,也就是我们常说的风格一致。

比如输入框该多高,错误提示怎么显示,字体大小颜色…之类的。

这个好办,我们把样式类写入一个公共样式文件form.wxss,然后需要的时候引入,甚至可以全局引入。

// form.wxss
.form {
 display: block;
 font-size: 28rpx;
 position: relative;
}
.form-line {
 background-color: #fff;
 border-bottom: 1px solid #e5e5e5;
 font-size: 34rpx;
 height: 96rpx;
 line-height: 96rpx;
 display: flex;
 padding: 0 31rpx;
}
.form-title {
 box-sizing: border-box;
 background-color: #efefef;
 color: #838383;
 font-size: 28rpx;
 padding: 31rpx;
 min-height: 90rpx;
}
...

我们使用的时候只需要在对应的元素上添加相应的样式即可。比如:

// xxx.wxml
<form class="form">
 <view class="form-title">请输入手机号</view>
 <view class="form-line">
 <label class="label">手机</label>
 <view class="form-control">
  <input class="f-1 va-m input" />
 </view>
 </view>
 ...
</form>

那么接下来我们只剩下校验规则和组件关联关系之间这两个难题了。

校验规则理想的状态是可扩展和可配置。

可扩展。随着业务的增长,在不修改已有规则情况可以新增校验规则。

可配置。可单独为每个表单组件配置不同的单个或多个校验规则。

如何做到可定义?用统一的形式即可。比如:

/*
统一的格式:
[规则名]: {
 rule: [校验方式]
 msg: [错误信息]
}
*/
const validators = {
 // 简单的校验用正则
 required: {
 rule: /.+/,
 msg: '必填项不能为空'
 },
 // 复杂的校验用函数
 same: {
 rule (val='', sVal='') {
  return val===this.data[sVal]
 },
 msg: '密码不一致'
 }
 ...
}

如何做到可配置?配置上支持类似数组的形式,然后用统一的函数依次读取这些校验规则,逐个校验。

配置的规则肯定是在原生表单组件上,至于组件的值也只能通过事件对象获取。

如果直接绑定事件进行校验会阻碍父页面获取值,所以最好由父页面绑定事件传值,并且传入事件对象和执行环境进行处理:

/*
校验函数部分代码
e 事件对象
context 页面对象函数执行的上下文环境
*/
let validate = (e, context) => {
 // 从事件对象中获取组件的值
 let value = (e.detail.value || '').trim()
 // 从事件中获取校验规则名称
 let validator = e.currentTarget.dataset.validator ? e.currentTarget.dataset.validator .split(',') : []
 // 遍历规则进行校验
 for (let i = 0; i < validator.length; i++) {
 let ruleName = validator[i].split('=')[0]
 let ruleValue = validator[i].split('=')[1]
 let rule = validators[ruleName].rule || /.*/
 if ('function' === typeof rule) {
  rule.call(context, value, ruleValue) ? '' : validators[ruleName].msg
 } else {
  rule.test(value) ? '' : validators[ruleName].msg
 }
 }
 ...
}

调用起来也非常简单,按照固定的格式加上对应的样式,配置校验规则,然后调用校验函数。

// 部分代码示例
// page.wxml
<form>
 <!-- 一个表单组件 -->
 <view class="form-line">
 <label class="label">授权手机</label>
 <view class="form-control">
  <!-- 校验规则:必须填写,且为电话号码 -->
  <input maxlength="11" class="f-1 va-m input" bindblur="validate" type="number" data-name="phone" data-validator="required,phone" confirm-type="next" value="{{phone}}" />
  <!-- 错误图标 -->
  <icon wx:if="{{form.phone!==undefined}}" type="{{form.phone?'warn':'success'}}" size="16" />
 </view>
 </view>
 ...
</form>
// page.js
valid(e) {
 this.setData({
 [e.currentTarget.dataset.name]: e.detail.value
 })
 validate(e, this)
}

上面的代码中省略了校验错误提示和非空校验。详细代码请查看GitHub仓库:

https://github.com/yalishizhude/miniprogram-seed.git

总结

写代码最然总是要抱着最美好的想法,但同时也要做着最坏的打算。尤其是面对一些底层框架限制的时候。

面对这种情况,我们要从核心需求出发,把能抽出公用的东西都出来,同时保证可配置、可扩展。

好的的架构师不但喜欢未开垦的处女地,也应不惧布满杂石乱草的荒野~

欢迎到评论区留言交流:https://github.com/yalishizhude/webclub-discuss/issues/1

为大家推荐现在关注度比较高的微信小程序教程一篇:《微信小程序开发教程》小编为大家精心整理的,希望喜欢。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# 微信小程序  # 表单校验  # 微信小程序中form 表单提交和取值实例详解  # 微信小程序 PHP后端form表单提交实例详解  # 微信小程序 表单Form实例详解(附源码)  # 微信小程序简单实现form表单获取输入数据功能示例  # 微信小程序表单验证功能完整实例  # 微信小程序 input表单与redio及下拉列表的使用实例  # 微信小程序表单验证form提交错误提示效果  # 微信小程序表单弹窗实例  # 微信小程序使用form表单获取输入框数据的实例代码  # 微信小程序学习笔记之表单提交与PHP后台数据交互处理图文详解  # 微信小程序bindinput与bindsubmit的区别实例分析  # 表单  # 的是  # 错误信息  # 绑定  # 错误提示  # 如果你  # 是在  # 又是  # 尤其是  # 都要  # 多个  # 也要  # 已有  # 还会  # 遍历  # 只需  # 说到  # 较高  # 要在  # 抱着 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在阿里云虚拟主机上快速搭建个人网站?  Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】  php做exe能调用系统命令吗_执行cmd指令实现方式【详解】  Laravel如何为API编写文档_Laravel API文档生成与维护方法  标题:Vue + Vuex 项目中正确使用 JWT 进行身份认证的实践指南  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  Laravel如何处理和验证JSON类型的数据库字段  如何在 Telegram Web View(iOS)中防止键盘遮挡底部输入框  nginx修改上传文件大小限制的方法  Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理  安克发布新款氮化镓充电宝:体积缩小 30%,支持 200W 输出  Laravel如何实现多语言支持_Laravel本地化与国际化(i18n)配置教程  如何利用DOS批处理实现定时关机操作详解  php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】  Bootstrap整体框架之CSS12栅格系统  如何快速生成专业多端适配建站电话?  如何注册花生壳免费域名并搭建个人网站?  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  黑客如何通过漏洞一步步攻陷网站服务器?  Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】  教你用AI润色文章,让你的文字表达更专业  南京网站制作费用,南京远驱官方网站?  php在windows下怎么调试_phpwindows环境调试操作说明【操作】  Linux网络带宽限制_tc配置实践解析【教程】  Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明  如何用免费手机建站系统零基础打造专业网站?  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  Laravel如何使用Guzzle调用外部接口_Laravel发起HTTP请求与JSON数据解析【详解】  如何在阿里云部署织梦网站?  如何自定义建站之星模板颜色并下载新样式?  iOS发送验证码倒计时应用  Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决  Python进程池调度策略_任务分发说明【指导】  利用python获取某年中每个月的第一天和最后一天  网易LOFTER官网链接 老福特网页版登录地址  香港服务器WordPress建站指南:SEO优化与高效部署策略  Laravel如何集成Inertia.js与Vue/React?(安装配置)  ,南京靠谱的征婚网站?  Android自定义控件实现温度旋转按钮效果  Swift中swift中的switch 语句  如何构建满足综合性能需求的优质建站方案?  如何快速搭建支持数据库操作的智能建站平台?  JS中对数组元素进行增删改移的方法总结  Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧  如何在阿里云ECS服务器部署织梦CMS网站?  如何在IIS管理器中快速创建并配置网站?  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  EditPlus中的正则表达式实战(5)  香港服务器网站生成指南:免费资源整合与高速稳定配置方案  详解vue.js组件化开发实践