layui form表单验证可以通过点击按钮触发,那可不可以通过js代码来触发表单验证?
官方回答是目前layui表单只是在监听提交的时候来验证。这样的话,我们想JS来触发的话,就需要修改源代码。从github上下载源码,打开src/lay/modules/form.js。找到验证的代码部分。
layui作者的注释说明很清晰。初步阅读一下验证代码。涉及到审查的元素是通过触发按钮获取的,所以提取代码需要进行稍微修改。
我们先把这段验证代码提取一下。
//原本的submit方法 //表单提交校验 var submit = function(){ var stop = null //验证不通过状态 ,verify = form.config.verify //验证规则 ,DANGER = 'layui-form-danger' //警示样式 ,field = {} //字段集合 ,button = $(this) //当前触发的按钮 ,elem = button.parents(ELEM) //当前所在表单域 ,verifyElem = elem.find('*[lay-verify]') //获取需要校验的元素 ,formElem = button.parents('form')[0] //获取当前所在的 form 元素,如果存在的话 ,filter = button.attr('lay-filter'); //获取过滤器 //开始校验 layui.each(verifyElem, function(_, item){ var othis = $(this) ,vers = othis.attr('lay-verify').split('|') ,verType = othis.attr('lay-verType') //提示方式 ,value = othis.val(); othis.removeClass(DANGER); //移除警示样式 //遍历元素绑定的验证规则 layui.each(vers, function(_, thisVer){ var isTrue //是否命中校验 ,errorText = '' //错误提示文本 ,isFn = typeof verify[thisVer] === 'function'; //匹配验证规则 if(verify[thisVer]){ var isTrue = isFn ? errorText = verify[thisVer](value, item) : !verify[thisVer][0].test(value); errorText = errorText || verify[thisVer][1]; if(thisVer === 'required'){ errorText = othis.attr('lay-reqText') || errorText; } //如果是必填项或者非空命中校验,则阻止提交,弹出提示 if(isTrue){ //提示层风格 if(verType === 'tips'){ layer.tips(errorText, function(){ if(typeof othis.attr('lay-ignore') !== 'string'){ if(item.tagName.toLowerCase() === 'select' || /^checkbox|radio$/.test(item.type)){ return othis.next(); } } return othis; }(), {tips: 1}); } else if(verType === 'alert') { layer.alert(errorText, {title: '提示', shadeClose: true}); } else { layer.msg(errorText, {icon: 5, shift: 6}); } //非移动设备自动定位焦点 if(!device.android && !device.ios){ setTimeout(function(){ item.focus(); }, 7); } othis.addClass(DANGER); return stop = true; } } }); if(stop) return stop; }); if(stop) return false; //获取当前表单值 field = form.getValue(null, elem); //返回字段 return layui.event.call(this, MOD_NAME, 'submit('+ filter +')', { elem: this ,form: formElem ,field: field }); };
提取验证部分。
//表单提交校验 var submit = function(){ var stop = null //验证不通过状态 ,verify = form.config.verify //验证规则 ,DANGER = 'layui-form-danger' //警示样式 ,field = {} //字段集合 ,button = $(this) //当前触发的按钮 ,elem = button.parents(ELEM) //当前所在表单域 ,verifyElem = elem.find('*[lay-verify]') //获取需要校验的元素 ,formElem = button.parents('form')[0] //获取当前所在的 form 元素,如果存在的话 ,filter = button.attr('lay-filter'); //获取过滤器 stop = validate(verifyElem); if(stop) return false; //获取当前表单值 field = form.getValue(null, elem); //返回字段 return layui.event.call(this, MOD_NAME, 'submit('+ filter +')', { elem: this ,form: formElem ,field: field }); }; /** * * @param {*} verifyElem 需要验证的元素 */ var validate=function(verifyElem){ var stop = null //验证不通过状态 ,verify = form.config.verify //验证规则 ,DANGER = 'layui-form-danger' //警示样式 ; //获取需要校验的元素 //开始校验 layui.each(verifyElem, function(_, item){ var othis = $(this) ,vers = othis.attr('lay-verify').split('|') ,verType = othis.attr('lay-verType') //提示方式 ,value = othis.val(); othis.removeClass(DANGER); //移除警示样式 //遍历元素绑定的验证规则 layui.each(vers, function(_, thisVer){ var isTrue //是否命中校验 ,errorText = '' //错误提示文本 ,isFn = typeof verify[thisVer] === 'function'; //匹配验证规则 if(verify[thisVer]){ var isTrue = isFn ? errorText = verify[thisVer](value, item) : !verify[thisVer][0].test(value); errorText = errorText || verify[thisVer][1]; if(thisVer === 'required'){ errorText = othis.attr('lay-reqText') || errorText; } //如果是必填项或者非空命中校验,则阻止提交,弹出提示 if(isTrue){ //提示层风格 if(verType === 'tips'){ layer.tips(errorText, function(){ if(typeof othis.attr('lay-ignore') !== 'string'){ if(item.tagName.toLowerCase() === 'select' || /^checkbox|radio$/.test(item.type)){ return othis.next(); } } return othis; }(), {tips: 1}); } else if(verType === 'alert') { layer.alert(errorText, {title: '提示', shadeClose: true}); } else { layer.msg(errorText, {icon: 5, shift: 6}); } //非移动设备自动定位焦点 if(!device.android && !device.ios){ setTimeout(function(){ item.focus(); }, 7); } othis.addClass(DANGER); return stop = true; } } }); if(stop) return stop; }); return stop; }
在暴露对象前,绑定方法给对象,当然暴露的方法需要新建一个,用于获取需要验证的元素,传入真正验证的方法。这里注意,返回true是表示有验证错误
/** * 触发验证,返回true/false,true是存在不符合 * @param {*} formFilter 表单筛选 */ var beforeValidate = function(formFilter){ //如果有传值则找到需要验证的表单,否则全部验证 var elemForm = $(ELEM + function(){ return filter ? ('[lay-filter="' + formFilter +'"]') : ''; }()), verifyElem = elemForm.find('*[lay-verify]'); return validate(verifyElem); }
在暴露的对象创建后,绑定方法。
//绑定验证方法 form.validate = beforeValidate;
然后进行测试,清空缓存,测试原来的功能。
再在控制台调用方法,模拟JS触发全局验证。
正常触发,再测试触发单个表单验证。
输入框执行聚集失败了。这应该是控制台把焦点抢了。
执行代码后马上将焦点放回页面。2秒后。
显示正常了。至此,改造form.js完成。