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完成。
