恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
layui输入框验证规则全解析:从lay-verify到form.verify的实践指南
首页
资讯中心
/
layui输入框验证规则全解析:从lay-verify到form.verify的实践指南
layui输入框验证规则全解析:从lay-verify到form.verify的实践指南
发布时间:2026/10/15 16:21:25
记得把 layui 输入框验证这套规则吃透你的表单才算真正能交付我最早接触 layui 输入框验证是在一个后台管理系统的重构项目里。当时表单提交前全靠自己写if (value )这种零散判断代码丑就算了还经常漏校验直到换用 layui 的form模块才意识到原来验证规则是可以声明式写的一行lay-verify就能解决大半问题。这篇文章就把我在项目中实际用下来的经验完整梳理一遍从内置规则到自定义规则从触发的底层逻辑到动态表单的坑照着做你基本不会再被表单校验这种事折腾。先说结论layui 输入框验证本质上是form模块对表单控件做的一次统一拦截处理lay-verify属性是声明验证意图的唯一入口form.verify()是注册自定义规则的唯一方法两者配合form.on(submit)的返回值就能覆盖绝大多数表单场景。它适合任何用 layui 做后台、做中后台、做管理端的前端开发者也适合刚接触 layui 想搞明白表单为什么“不校验”的新手。1. 先搞清楚 layui 验证这套东西是怎么跑起来的很多人用 layui 验证只知道往input上写lay-verifyrequired但不知道这套机制背后依赖的是form模块的渲染流程。你写的那一串 HTML 并不直接等于“可验证的表单”必须经过form.render()接管之后layui 才能识别你的验证规则。这一步不理解后面碰到的很多“灵异问题”都会让你怀疑人生。1.1 表单渲染是整个验证体系的触发前提layui 的表单控件包括输入框、下拉、单选框、复选框默认有一套自己的样式和事件绑定逻辑。你在页面里写的input classlayui-input只有调用了form.render()之后才会被 layui 的 form 模块正式接管。这个接管动作干的事很多但和我们验证相关的关键点就一个把lay-verify属性解析成内部验证规则表。很多同学踩过的第一个坑就来自这里。动态往 DOM 里 append 一段带lay-verifyrequired的输入框结果点提交没有任何反应原因就是没有在 append 之后重新执行form.render(form)。不渲染规则就注册不上验证自然不生效。还有一点要注意form.render()是有类型的。默认form.render()会渲染所有表单但更推荐写form.render(null, filterName)指定渲染某个lay-filter对应的表单容器这样性能更好也不会误伤页面上其他表单区域。1.2 lay-verify 属性到底在声明什么lay-verify这个属性是验证规则的载体它的值有三种写法单个规则名lay-verifyrequired多个规则名用英文竖线分隔lay-verifyrequired|phone直接写正则表达式lay-verifyregexp这里要注意直接写正则时斜杠/会和规则分隔符产生歧义layui 自身文档里很少推荐这种用法实际项目中我基本不用因为可读性太差。多规则组合是我在真实项目中用得最多的形式比如用户注册表单里的手机号输入框我会写成lay-verifyrequired|phone一行代码同时搞定“必填”和“格式校验”。需要注意的是多条规则的执行顺序就是从左到右如果前面的规则失败了后面的规则不会继续执行之前的校验提示会直接展示出来。1.3 从点击提交到验证失败的完整链路我把这套流程拆开讲。当你给一个按钮加上lay-submit lay-filterdemoSubmit点击它时 form 模块会做几件事收集当前表单作用域下所有“已被渲染”的控件值。遍历这些控件逐个检查它们的lay-verify规则。如果某条规则校验失败中断后续控件的校验并弹出对应的错误提示默认是 layer.tips 样式的小气泡。所有校验通过后触发form.on(submit(demoSubmit))回调。在回调里返回false才能阻止页面刷新或跳转如果你没写return false表单就会走原生提交逻辑验证等于白做。这里最容易被忽略的是第 5 步。我见过太多人写了lay-submit和规则却忘了在回调里return false结果 verify 通过了表单却直接刷新页面数据没提交到后端。记住layui 的验证只是“拦截”不会替你阻止表单默认行为阻止提交是你自己在回调里干的事。2. 内置规则清单与实际使用中的细节实测下来layui 内置的验证规则能解决大概七成到八成的常规需求。但内置规则的使用有一些细节网上文档写得很简略我结合项目经验一个个说清楚。2.1 常用内置规则逐项拆解下面是我在一线项目里最常用、也推荐你重点掌握的几条规则规则名校验内容实测注意事项required是否为空会过滤纯空格字符串但源码实现是value 才判空手动拼接的空格也可能被判为有值phone手机号格式只做宽松的前缀与长度判断不保证一定是真实在网的号码email邮箱格式对ab这种极简形式也会放行但一般够用url网址格式要求带协议头www.xxx.com会被判失败必须在规则前让用户按https://格式输入number是否为数字允许负数、小数、科学计数法不完全支持实测负数和普通小数没问题date日期格式实际执行的是date类型控件自带校验要求严格符合YYYY-MM-DD结构你可能会问phone的“宽松判断”到底宽松到什么程度我特意去翻过 layui 的源码它本质上就是一个正则匹配具体到项目中如果你的业务需要更严格的手机号校验比如必须 1 开头、11 位、第二位是 3/5/7/8/9那内置的phone就不够用了这种情况我建议直接写自定义规则别在纯前端层面和运营商号段较劲。2.2 多规则组合的优先级与执行顺序多规则用|拼接这条语法很简单但执行顺序和“短路”特性需要你心里有数。以前我做过一个场景输入框既要必填又要是正整数。我写了lay-verifyrequired|number结果有用户输入了-5number 规则通过了但因为没校验正负负数照样提交了。这个问题后来是通过自定义positiveInt规则解决的。多规则的执行是“遇错即停”的。这意味着如果你把required放在最后用户完全没填内容时先走的可能是格式规则弹出的提示会变成“格式不正确”而不是“请填写”体验很怪。所以必填永远排第一这是我自己的硬性规范。再补一个正则里带|的经典陷阱。假设你想让输入框同时允许手机号和座机号如果写成lay-verifyphone|tel这是规则的组合没毛病。但如果想直接在lay-verify里写一个包含|的正则比如/^1\d{10}$|^0\d{2,3}-?\d{7,8}$/那 layui 解析到第一个|时会以为你在分隔两条规则整个正则就废了。解决方案是先注册成自定义规则再写在lay-verify里。2.3 必填提示信息的自定义lay-reqtext 与 lay-msglay-verifyrequired默认弹出的消息是“此项必填”这在做中英文切换或更优雅的提示语时不够友好。layui 提供了lay-reqtext属性专门用来覆盖“必填”校验失败时的提示文字。比如input lay-verifyrequired lay-reqtext用户名不能为空 placeholder请输入用户名这个属性只对required规则生效而且只在必填失败时展示。那非必填规则比如邮箱格式错了怎么自定义提示这就轮到lay-msg属性出马了input lay-verifyemail lay-msg请输入正确的邮箱地址lay-msg的优先级高于规则名称对应的默认提示文本但又低于lay-reqtext对必填场景的覆盖。换句话说如果你同时写了lay-verifyrequired|email和lay-msg格式不正确但用户没填内容弹出的还是lay-reqtext的内容只有格式不对时lay-msg才生效。这块的坑在于很多人为了图省事只写lay-reqtext不写lay-msg结果格式类规则错误时提示全是默认的英文规则名比如直接弹 “phone” 或 “email”看到这种提示的用户基本是懵的。我现在的习惯是必填写lay-reqtext 规则名格式类规则至少给关键项配lay-msg。3. 自定义验证规则真正拉开项目质量差距的地方内置规则再丰富也没法覆盖业务里五花八门的校验需求两次密码是否一致、身份证号格式、金额是否不超过某个上限这些全得靠form.verify自定义规则来实现。这一节我把注册机制、写法规范、执行机制讲透。3.1 form.verify 注册机制的底层逻辑form.verify的用法很简单form.verify({ pwd: function(value, item) { if (!/^[\S]{6,12}$/.test(value)) { return 密码长度必须在 6 到 12 位且不能包含空格; } } });注册之后输入框上写lay-verifypwd就能用。这里有两个很多人没注意到的点。第一规则名不能和内置规则重名。如果你定义了phone自定义规则它会覆盖内置的phone。某次我就因为一个同事自定义了email规则为了更严格校验结果项目里所有邮箱输入框的验证逻辑全变了排查了很长时间。建议团队内部对所有自定义规则名加上前缀比如mr_phone、ck_pwd避免和内置规则撞车。第二函数里return一个字符串layui 会把这个字符串当作错误提示信息弹出不return即返回undefined就表示校验通过。所以不要写return false或return true那会被当作错误提示文本显示真的很滑稽我亲眼见过表单里弹出“true”这个提示。第三item参数拿到的就是当前 input 的 DOM 对象。这意味着你可以在校验逻辑里基于这个 DOM 做更多事比如判断它是否处于某种状态、读取它的>input idpwd lay-verifypwd placeholder密码 input idconfirmPwd lay-verifyconfirmPwd placeholder再次输入密码form.verify({ confirmPwd: function(value, item) { var pwdVal $(#pwd).val(); if (value ! pwdVal) { return 两次输入的密码不一致; } } });这里要注意获取“原密码值”的时机和选择器。如果你在规则函数里$(#pwd).val()拿到的是空先想想是不是这个 jQuery 对象没选对更健壮的做法是给原密码框设置id或用name属性查找。如果原密码框本身值也变了建议先触发原密码框的验证但 layui 没有直接的方法去手动触发另一控件的校验所以实际项目里多半是把密码和确认密码放在同一规则体系下保证先填密码再填确认密码。再来看“金额上限”的校验。比如报销表单里金额不能超过 5000同时必须是正数且最多两位小数form.verify({ amount: function(value) { if (!/^\d(\.\d{1,2})?$/.test(value)) { return 金额格式错误最多保留两位小数; } if (parseFloat(value) 5000) { return 单笔金额不能超过 5000 元; } } });这种多条件校验可以全部写在同一个规则函数里按“格式优先、范围其次”的顺序判断。如果先判范围再判格式用户输入一个逗号分隔的数字比如5,000格式校验没拦住范围判断可能误报“超过上限”提示信息就错了。所以格式正则永远放最前面。第三个高频是“不允许输入纯空格”。我把它封装成一个规则noBlank因为内置required对纯空格是放行状态。你可以拿去做任意输入框的附加规则比如lay-verifyrequired|noBlank或单独对某个多行文本域做校验。form.verify({ noBlank: function(value) { if ($.trim(value) ) { return 内容不能为纯空格; } } });3.3 正则直接写在 lay-verify 里的方案取舍虽然前面说过不推荐直接写正则但偶尔为了临时校验确实有人这么干。layui 的规则解析逻辑是如果lay-verify的值在已注册规则里找不到它会把值当作正则表达式来测试实际上源码里会对lay-verify里的每个规则名做一次正则测试如果匹配到斜杠/开头就按正则处理。但问题也很明显项目代码里写这种正则后续维护的人完全看不懂而且很难做规则复用。一个同样格式的校验昨天写在 A 表单今天要复制到 B 表单只能复制一串正则字符串一旦格式调整所有地方都要改。所以我给自己定的规矩是所有正则校验一律注册成带语义的自定义规则只有极少数一次性的临时校验才允许写在lay-verify里且必须加注释说明。4. 一个完整的注册表单实操从结构到提交调通理论讲了一堆落到实际才见真章。我用一个用户注册表单把整个流程串起来包括表单结构、验证规则、提交处理、动态渲染所有代码都是我在项目中实际跑通的版本。4.1 表单结构设计先看 HTML 结构。我把每个输入框的lay-verify和placeholder都提前规划好form classlayui-form lay-filterregisterForm div classlayui-form-item label classlayui-form-label用户名/label div classlayui-input-block input typetext nameusername lay-verifyrequired|username lay-reqtext用户名不能为空 placeholder4-16位字母或数字 classlayui-input /div /div div classlayui-form-item label classlayui-form-label密码/label div classlayui-input-block input typepassword namepassword lay-verifyrequired|pwd lay-reqtext密码不能为空 placeholder6-12位非空字符 classlayui-input autocompleteoff /div /div div classlayui-form-item label classlayui-form-label确认密码/label div classlayui-input-block input typepassword nameconfirmPwd lay-verifyrequired|confirmPwd lay-reqtext请再次输入密码 placeholder再次输入密码 classlayui-input autocompleteoff /div /div div classlayui-form-item label classlayui-form-label手机号/label div classlayui-input-block input typetext namephone lay-verifyrequired|phone|realPhone lay-reqtext手机号不能为空 lay-msg手机号格式不正确 placeholder请输入手机号 classlayui-input /div /div div classlayui-form-item label classlayui-form-label邮箱/label div classlayui-input-block input typetext nameemail lay-verifyrequired|email lay-reqtext邮箱不能为空 lay-msg邮箱格式不正确 placeholder请输入邮箱 classlayui-input /div /div div classlayui-form-item div classlayui-input-block button classlayui-btn lay-submit lay-filterregisterSubmit立即注册/button button typereset classlayui-btn layui-btn-primary重置/button /div /div /form这里我额外加了一条realPhone自定义规则用来做比内置phone更严格的校验1 开头、11 位。这就是前面说的“内置规则 自定义规则叠加”的典型样板。4.2 自定义规则注册与初始化接下来是 JS 部分需要特别注意form.verify必须在form.render()之前执行。因为form.render()会把已经声明的验证规则绑定到对应控件上顺序反了动态声明再晚也来不及了。layui.use([form, layer], function() { var form layui.form; var layer layui.layer; // 1. 先注册自定义校验规则 form.verify({ username: function(value) { if (!/^[a-zA-Z0-9]{4,16}$/.test(value)) { return 用户名需为4-16位字母或数字; } }, pwd: function(value) { if (!/^[\S]{6,12}$/.test(value)) { return 密码长度为6-12位不能包含空格; } }, confirmPwd: function(value) { var firstPwd $(input[namepassword]).val(); if (value ! firstPwd) { return 两次输入的密码不一致; } }, realPhone: function(value) { if (!/^1[3-9]\d{9}$/.test(value)) { return 请输入正确的11位手机号; } } }); // 2. 渲染表单让规则生效 form.render(null, registerForm); // 3. 监听提交 form.on(submit(registerSubmit), function(data) { var field data.field; console.log(提交的数据是, field); // 这里一般发 ajax 到后端 $.ajax({ url: /api/register, type: post, data: field, dataType: json, success: function(res) { if (res.code 0) { layer.msg(注册成功); } else { layer.msg(res.msg || 注册失败); } } }); return false; }); });这个写法里顺手验证了几件事。data.field会拿到所有带name属性的表单值不需要自己逐个取confirmPwd规则里$(input[namepassword]).val()在点击提交时一定能取到值因为用户先填完密码才会点按钮时序上没问题。4.3 form.render 的动态场景与重渲染后台管理页面经常出现“点击新增按钮弹出一个带表单的弹层”这种情况。弹层内容是动态生成的 HTML这时候必须等弹层渲染完成后再调用form.render()否则一旦lay-verify规则没绑定点提交弹层里的就会跳到浏览器默认提交行为。我的推荐写法是在弹层渲染的回调里执行渲染layer.open({ type: 1, content: $(#addFormTpl).html(), success: function(layero, index) { form.render(null, addFormFilter); } });success回调会在弹层内容插入 DOM 完成后触发此时再渲染表单必然能拿到新增的输入框。另一个容易遗漏的点是表单模板比如放在script typetext/html里你取它.html()之前模板里已经写好了lay-verifyform.render()之后才能识别顺序一定不能反。5. 常见问题与排查经验速查表单校验这种东西出了问题往往不是“不知道怎么做”而是“看起来很正常的代码就是不生效”。我整理了自己项目中踩过、也帮别人排查过的几类典型问题按出现频率排序你能少走不少弯路。5.1 点击提交毫无反应到底为什么这是最高频的问题。我总结下来有四个常见原因没有引入或渲染 form 模块。写了lay-verify却没执行form.render()验证规则永远不会被注册。按钮没写lay-submit或lay-filter。没有lay-submit的按钮即使绑定点击事件也不会走 layui 的验证拦截链路没有lay-filterform.on(submit(...))根本监听不到。表单没加classlayui-form。form.render()也是按layui-form作用域找表单的你把它当成普通form用验证就是个摆设。提交回调里没return false。这个我前面提过验证是通过了但页面刷新或被原生提交接管看起来就像“没拦住”。排查顺序建议先确认classlayui-form存在 → 再确认按钮有lay-submit和lay-filter→ 再看 JS 里有没有form.render()→ 最后看form.on(submit)回调里有没有return false。按这个顺序来基本几分钟能定位。5.2 动态加载的表单不校验怎么解决弹层、异步加载、拖拽生成的输入框这三类都属于“后来才出现的 DOM”。你必须在它们进入页面后重新执行form.render()。很多人以为渲染一次就万事大吉实际上每新增一个控件就要在那个时间点重新渲染一次。一个更隐蔽的情况你先调用了form.render()之后用 jQuery 把某个input的lay-verify属性改了比如从可选改成必填再点提交新属性不生效。因为渲染时读取的规则早已绑定到内部机制里不会因为你改了 HTML 属性就自动同步。解决办法同样是修改后重新form.render()或者干脆不要用这种“改属性”的方式而是用form.verify和 JS 控制开关。5.3 验证通过但提交的数据有问题这种情况通常出现在“验证校验过了但提交的数据不符合业务要求”上。比如我做过一个部门选择下拉lay-verifyrequired能保证用户选中了某项但它选中的是默认占位项value 为空字符串required对下拉框的判空逻辑有时会把占位项当成“有值”。原因在于 layui 对下拉框的required校验是看是否选中了value的 option或者是否选中了非lay-ignore的第一个 option实际测试中如果 placeholder 用lay-ignore跳过渲染可能出现特殊表现。这类问题的排查思路只有一个后端永远不要信任前端校验结果。前端校验只是提升用户体验真正的合法性校验必须在后端再做一次。我在项目里给前端的铁律是纯前端验证通过后提交的数据如果后端校验退回来前端必须能把后端返回的错误信息准确展示到对应输入框上而不是弹一个笼统的“提交失败”。5.4 自定义规则不执行的可能原因如果你发现自定义规则里的return 提示信息根本没弹出来先检查两件事规则名是否写进了lay-verify并且和form.verify({})里的键名完全一致大小写、空格都算。form.verify({})是否在form.render()之前调用。如果你先渲染后注册重新渲染才能补上。还有一种情况是layui.use里的异步问题。如果你的自定义规则定义在外部 JS 文件里而这个文件晚于layui.use回调执行那规则自然找不到。我的做法是所有form.verify统一收敛到一个模块里导出页面引入时保证在layui.use回调里同步调用后再form.render()。5.5 验证提示样式太突兀如何调整layui 默认的验证提示是layer.tips风格的小黄条位置跟随输入框。实际项目中有些设计师觉得这个提示条干扰布局要求改成输入框下方红字。实现方式有两个层次一是用form.verify返回错误信息后自己监听layui的验证失败事件问题是 layui 没有公开的验证失败事件钩子只能靠拦截默认提示再处理比较复杂。二是直接修改源码或 CSS 覆盖.layui-form-danger等样式的表现方式。我推荐做轻量级调整把提示位置、配色统一成一个class然后在form.render()后重写对应样式不要大改源码否则升级版本时容易积累大量兼容问题。6. 我在实际项目里的一些体会与建议到这里layui 输入框验证规则的核心用法和坑点都讲得差不多了。最后说几点我个人在实际操作中的体会不是书上的话是真的在项目里熬过夜换来的。第一一开始就把自定义验证规则集中管理。我见过很多项目每个页面各自写各自的form.verify光一个“手机号”规则就有三种写法有的用内置phone有的自定义^1[3-9]\d{9}$有的连88这种号段都匹配到了。时间一长没人能说清这套系统的验证底线是什么。我现在做项目第一件事就是建一个validateRules.js所有通用规则都放在这里统一导出页面按需引入格式和提示语全局一致。第二验证提示文案要写人话。你写return 格式错误普通用户看不懂到底哪里错了。我自己的文案规范是“具体到字段 具体到格式要求 示例”比如“手机号格式不正确请输入11位数字例如 13800138000”。这样的提示几乎不需要用户再去猜。反例就是lay-msg格式不对这种提示除了让用户烦没有任何价值。第三前端验证和后端验证永远是一对搭档。前端的目标是让用户少提交一次把明显不合法的数据拦在门外后端的目标是保证入库的数据绝对安全。这两层职责明确后你的代码结构也会清晰很多。我见过有团队把非常复杂的业务规则比如“请假天数不能超过剩余年假数”全堆在前端结果后端根本不管一调接口数据就穿帮。正确的做法是前端做及时反馈后端做最终裁决。第四测试验证规则一定要覆盖边界值。不要只测“填对了能不能过”要专门测空值、纯空格、超长文本、emoji、特殊符号、复制粘贴带换行的情况。我自己吃过一次亏用户往用户名里粘贴了带\n的内容前端正则没拦结果后端数据库字段直接被换行弄乱了格式。所以凡是你写了自定义正则的地方建议在交付前专门跑一轮边界字符测试。要是真想把这个技能练到熟练我建议你重新审视一下手头所有写过的表单哪些用了布尔判断堆积出来的校验改成lay-verify会清爽多少哪些自定义规则是重复的抽出来能合并成一个公共模块。改完你会明显感觉到表单校验这件事从“想起来就烦”变成“按部就班闭眼也能处理”。这个感觉就是熟练度真正到位了的标志。