Open Lenny-Hu opened 4 years ago
体积有点大
https://baianat.github.io/vee-validate/
import Vue from 'vue'
import VeeValidate, { Validator } from 'vee-validate'
import zh from 'vee-validate/dist/locale/zh_CN'// 引入中文文件
// 配置中文
Validator.addLocale(zh)
const config = {
errorBagName: 'errors', // change if property conflicts.
fieldsBagName: 'fieldBags', // 报冲突时 可自定义修改字段名称
delay: 0, // 错误提示的延迟时间
strict: true, // 没有设置规则的表单不进行校验,
enableAutoClasses: false,
locale: 'zh_CN', // 对语言(中文)的配置
classNames: {
touched: 'touched', // the control has been blurred
untouched: 'untouched', // the control hasn't been blurred
valid: 'valid', // model is valid
invalid: 'invalid', // model is invalid
pristine: 'pristine', // control has not been interacted with
dirty: 'dirty' // control has been interacted with
},
events: 'input', //* *input|blur** 在用户输入和表单失去焦点时都进行校验 可单独写 blur或input
inject: true
}
Vue.use(VeeValidate, config)
// 自定义validate
const dictionary = {
zh_CN: {
messages: {
email: () => '请输入正确的邮箱格式',
required: (field) => '请输入' + field
},
attributes: {
email: '邮箱',
password: '密码',
task_name: '任务名称',
phone: '手机',
task_type: '任务类型',
task_template: '任务模板',
task_tine_type: '时间类型',
task_tine_value: '时间类型值',
assisting_department: '协助单位',
responsible_department: '责任单位',
target_area: '目标新增面积',
target_cahnge_number: '目标改造数量',
implementation_plan: '实施方案',
assessment_standard: '考核指标',
grading_standard: '评分标准',
score: '考核分值'
}
}
}
Validator.updateDictionary(dictionary)
Validator.extend('phone', {
messages: {
zh_CN: field => field + '必须是11位手机号码'
},
validate: value => {
return value.length === 11 && /^((13|14|15|17|18)[0-9]{1}\d{8})$/.test(value)
}
})
例如
// 先加载vue、vee-validate、zh-cn文件,再加载下列代码
// vee-validate 公共规则、设置
(function () {
Vue.use(window.VeeValidate, {
locale: 'zh_CN'
}); // 使用vue插件
// 自定义规则
window.VeeValidate.Validator.extend('phone', {
getMessage: function (field) {
return field + '必须是11位号码';
},
validate: function (value) {
return /^1[3-9]\d{9}$/.test(value);
}
});
// 定义全局错误信息
var dictionary = {
zh_CN: {
messages: {
email: function () {
return '请输入正确的邮箱';
},
required: function (field) {
return '请输入' + field;
}
}
// attributes: {
// mobile: '电话',
// address: '地址'
// }
}
}
window.VeeValidate.Validator.localize(dictionary);
})();
https://l-ui.com/content/apis/validate.html https://www.zhangxinxu.com/wordpress/2012/12/jquery-html5validate-html5-form-validate-plugin/
html
<form class="js-form">
<ul>
<li class="">
<div class="">
<input
type="text"
value=""
placeholder=""
name="realName"
>
</div>
</li>
<li class="">
<div class="">
<input type="text" value="" placeholder="请输入手机号" name="mobile">
</div>
</li>
<li class="">
<div class="">
<input type="text" value="" placeholder="请输入图形验证码" name="captcha">
</div>
</li>
<li class="sms-code">
<div class="">
<input type="text" value="" placeholder="请输入短信验证码" name="code">
</div>
</li>
<li class="check-box">
<div class="">
<input type="checkbox" name="checkbox" id="" value="checkbox1">
<input type="checkbox" name="checkbox" id="" value="checkbox2">
<input type="checkbox" name="checkbox" id="" value="checkbox3">
<input type="checkbox" name="checkbox" id="" value="checkbox4">
</div>
</li>
<li class="radio-box">
<div class="">
<input type="radio" name="radio" id="" value="radio1">
<input type="radio" name="radio" id="" value="radio2">
<input type="radio" name="radio" id="" value="radio3">
</div>
</li>
<li class="select-box">
<div class="">
<select name="select" id="" multiple>
<option value="option1">option1</option>
<option value="option2">option2</option>
<option value="option3">option3</option>
</select>
</div>
</li>
<li class="textarea-box">
<div class="">
<textarea name="textarea" id="" cols="30" rows="10"></textarea>
</div>
</li>
<li class="file-box">
<div class="">
<input type="file" name="file" id="">
</div>
</li>
</ul>
</form>
/**
* 简单的表单验证器
* @param {$元素对象} $box 表单的容器
* @param {object} rules 验证规则
*/
function Validator ($box, rules) {
this.$box = $box;
this.rules = rules;
this.results = {
valid: true, // 验证通过标识
errors: [], // 错误列表
data: {} // 表单数据
};
}
// 处理错误消息
Validator.prototype.handleMsg = function (eleData, rule, errMsg) {
if (errMsg) {
this.results.valid = false;
var error = {
name: eleData.name,
label: rule.label,
message: errMsg
};
this.results.errors.push(error);
eleData.$ipts.addClass('invalid').parent().addClass('invalid-box');
} else {
eleData.$ipts.removeClass('invalid').parent().removeClass('invalid-box');
}
// 错误消息(错误消息可用css+伪元素方式显示在界面上)
eleData.$ipts.parent().attr('data-invalid-msg', errMsg || '');
}
// 非空验证
Validator.prototype.required = function (eleData, rule) {
if (!rule.required) {
return true;
}
var valid = false;
// 根据不同类型的元素执行不同的检查方式
switch (eleData.type) {
case 'checkbox':
case 'radio':
eleData.$ipts.each(function (i, e) {
valid = e.checked;
return e.checked ? false : true;
});
break;
default:
valid = !!eleData.iptVal;
break;
}
this.handleMsg(eleData, rule, valid ? '' : rule.label + '不能为空');
return valid;
}
// 自定义正则检查
Validator.prototype.test = function (eleData, rule) {
if (!(Array.isArray(rule.patterns) && rule.patterns.length)) {
return true;
}
var valid = false;
var message = '';
for (var j = 0; j < rule.patterns.length; j++) {
var v = rule.patterns[j];
valid = v.pattern.test(eleData.iptVal);
message = valid ? '' : v.message
if (!valid) {
break;
}
}
this.handleMsg(eleData, rule, message);
return valid;
}
// 数据长度检查
Validator.prototype.datalength = function (eleData, rule) {
if (!rule.maxlength && !rule.minlength) {
return true;
}
// 无需检查的元素
if (['radio', 'select-one'].includes(eleData.type)) {
return true;
}
var maxlength = rule.maxlength || Infinity;
var minlength = rule.minlength || 0;
var valid = false;
var message = '';
// 处理select和checkbox
var handleMsg = function (count, type) {
var msgMap = {
option: {
maxlength: rule.label + '最多选择' + maxlength + '项',
minlength: rule.label + '最少选择' + minlength + '项'
},
text: {
maxlength: rule.label + '最大长度应为' + maxlength + '位字符',
minlength: rule.label + '最小长度应为' + minlength + '位字符'
}
};
// 最大
valid = maxlength >= count;
if (!valid) {
message = msgMap[type].maxlength;
return false;
}
// 最小
valid = count >= minlength;
if (!valid) {
message = msgMap[type].minlength;
return false;
}
}
switch (eleData.type) {
case 'checkbox':
var checkedCount = 0;
eleData.$ipts.each(function (i, e) {
e.checked && checkedCount++;
});
handleMsg(checkedCount, 'option');
break;
case 'select-multiple':
var selectedCount = eleData.$ipts[0].selectedOptions.length;
handleMsg(selectedCount, 'option');
break;
case 'file':
var files = eleData.$ipts[0].files;
// ie9等没有files属性的浏览器忽略
if (!files) {
valid = true;
} else {
for (var index = 0; index < files.length; index++) {
var item = files[index];
// 只检查文件的最大大小
valid = maxlength >= item.size;
if (!valid) {
message = rule.label + '文件最大限制大小为' + (maxlength / 1024) + 'KB';
break;
}
}
}
break;
default:
handleMsg(eleData.iptVal.length, 'text');
break;
}
this.handleMsg(eleData, rule, message);
return valid;
}
// 文件后缀名检查
Validator.prototype.suffix = function (eleData, rule) {
if (!(Array.isArray(rule.suffixs) && rule.suffixs.length)) {
return true;
}
// 无需检查的元素
if (eleData.type != 'file') {
return true;
}
var valid = false;
valid = rule.suffixs.some(function (v, i) {
return eleData.iptVal.endsWith(v);
});
this.handleMsg(eleData, rule, valid ? '' : rule.label + '文件后缀只能是' + rule.suffixs.join('、'));
return valid;
}
// 数字大小范围检查
Validator.prototype.range = function (eleData, rule) {
if (!rule.min && !rule.max) {
return true;
}
// 无需检查的元素
if (!['text', 'number'].includes(eleData.type)) {
return true;
}
var valid = false;
var message = '';
var max = rule.max || Infinity;
var min = rule.min || -10000 * 10000;
var number = parseFloat(eleData.iptVal);
if ((valid = isNaN(number))) {
message = rule.label + '不是一个合法的数字';
} else {
valid = max >= number;
if (!valid) {
message = rule.label + '最大应该为' + max;
}
valid = number >= min;
if (!valid) {
message = rule.label + '最小应该为' + min;
}
}
this.handleMsg(eleData, rule, message);
return valid;
}
// 添加合法的数据
Validator.prototype.pushData = function (eleData) {
var data = [];
switch (eleData.type) {
case 'checkbox':
case 'radio':
eleData.$ipts.each(function (i, e) {
if (e.checked) {
data.push(e.value);
}
});
break;
case 'select-one':
case 'select-multiple':
for (var index = 0; index < eleData.$ipts[0].selectedOptions.length; index++) {
var e = eleData.$ipts[0].selectedOptions[index];
data.push(e.value);
}
break;
case 'file':
this.results.data[eleData.name] = eleData.$ipts[0].files;
return true;
break;
default:
data.push(eleData.iptVal);
break;
}
this.results.data[eleData.name] = data.join(',');
}
// 检查
Validator.prototype.validate = function () {
for (var key in this.rules) {
console.log(key);
if (!this.rules.hasOwnProperty(key)) {
continue;
}
var rule = this.rules[key];
var $ipts = this.$box.find('[name="' + key + '"]');
if (!$ipts.length) {
continue;
}
var eleData = {
name: key,
nodeName: $ipts[0].nodeName.toLowerCase(),
type: $ipts.attr('type').toLowerCase(),
iptVal: $.trim($ipts.val()),
$ipts: $ipts
};
// 非空
if (!this.required(eleData, rule)) {
continue;
}
// 长度和大小
if (!this.datalength(eleData, rule)) {
continue;
}
// 大小范围
if (!this.range(eleData, rule)) {
continue;
}
// 文件后缀检查
if (!this.suffix(eleData, rule)) {
continue;
}
// 自定义规则
if (!this.test(eleData, rule)) {
continue;
}
// 将合法数据添加到data
this.pushData(eleData);
}
return this.results;
}
使用
var rules = {
realName: {
label: '真实姓名',
required: true
},
mobile: {
label: '手机号',
required: true,
patterns: [
{
pattern: /^1[3-9]\d{9}$/,
message: '请输入合法的手机号'
}
]
},
captcha: {
label: '图形验证码',
required: true,
max: 4,
min: 1
},
code: {
label: '短信验证码',
required: true,
maxlength: 4,
minlength: 4
},
checkbox: {
label: 'checkbox',
required: true,
maxlength: 3
},
radio: {
label: 'radio',
required: true
},
select: {
label: 'select',
required: true,
minlength: 2
},
textarea: {
label: 'textarea',
required: true,
minlength: 10,
maxlength: 20
},
file: {
label: 'file',
required: true,
maxlength: 1024 * 1024,
suffixs: ['zip', 'docx']
}
};
var validateRes = (new validator(self.$el.find('.js-form'), rules)).validate();
console.log(validateRes);
vuelidate
https://github.com/vuelidate/vuelidate