[完善]表单使用async-validator4.0.7实现校验功能

🐛[修复]下拉框点击自身不能隐藏和设置modelValue为空时不能置空下拉框
This commit is contained in:
xumi
2021-12-19 07:12:33 +08:00
parent 63d1e7538d
commit cd727c0ef5
9 changed files with 912 additions and 33 deletions

View File

@@ -1,25 +1,140 @@
<template>
<form class="layui-form" @submit="submit">
<form class="layui-form" :onsubmit="submit">
<slot />
</form>
</template>
<script setup name="LayForm" lang="ts">
<script lang="ts">
export default{
name: 'LayForm'
}
</script>
<script setup lang="ts">
import { toRefs, provide,reactive, onMounted } from "vue"
import { Rule, ValidateError, ValidateMessages } from "async-validator"
import {layFormKey, LayFormItemContext, FormCallback, modelType} from "../type/form"
const props = withDefaults(
defineProps<{
model?: object
model?: modelType
required?: boolean,
rules?: Rule,
initValidate?: boolean,
requiredIcons?: string,
requiredErrorMessage?: string,
validateMessage?: ValidateMessages,
useCN?: boolean
}>(),
{
model: function(){
return {}
}
},
useCN : true,
requiredIcons : '',
initValidate : false
}
)
const formItems : LayFormItemContext[] = [];
const formItemMap : {[key:string]:LayFormItemContext} = {};
const emit = defineEmits(['submit'])
// 初始化表单就进行校验
onMounted(()=>{
props.initValidate && validate()?.catch(err => {});
})
// 原生提交表单事件
const submit = function () {
emit('submit',props.model)
let _isValidate = false;
validate((isValidate, model, errors) => {
_isValidate = isValidate as boolean;
emit('submit', isValidate, model, errors);
});
// 如果表单失败则阻止提交表单,成功则进行提交表单
return _isValidate;
}
/**
* 校验表单数据
* @param fields 需要校验的表单字段(string|string[]); 该字段如果为function, 则默认为回调函数,校验全部字段;
* @param callback 校验表单之后的回调函数
**/
const validate = function(fields?: string|string[]|FormCallback|null, callback?: FormCallback | null){
// 根据参数识别需要校验的表单项
let validateItems : LayFormItemContext[] = formItems;
if (typeof fields === 'function') {
callback = fields;
} else if (typeof fields === 'string' || (Array.isArray(fields) && fields.length > 0)) {
validateItems = [];
const validateFields = !fields ? [] : ([] as string[]).concat(fields);
validateFields.forEach(field => formItemMap[field] && validateItems.push(formItemMap[field]));
}
// 通过调用每个子项进行校验
let errorsArrs: ValidateError[] = [];
validateItems.forEach(filed => {
filed.validate((errors, _fields)=>{
errorsArrs = errorsArrs.concat(errors as ValidateError[]);
});
});
const isValidate = errorsArrs.length === 0;
// 有回调则进行回调
if (typeof callback === 'function') {
isValidate ? callback(true, props.model, null) : callback(false, props.model, errorsArrs);
return null;
}
// 没有回调则创建一个Promise的链式调用
return new Promise((resolve, reject) => {
const callbackParams = {
isValidate,
model : props.model,
errors: isValidate ? null : errorsArrs
};
callbackParams.isValidate ? resolve(callbackParams) : reject(callbackParams);
});
}
/**
* 清除校验
* @param fields 需要进行清除校验的表单字段(string|string[]); 该字段如果为null, 则默认为全部字段清除校验;
**/
const clearValidate = function(fields?: string | string[]){
const clearFields = !fields ? [] : ([] as string[]).concat(fields);
if (clearFields.length === 0) {
formItems.forEach(filed => filed.clearValidate());
} else {
clearFields.forEach(field => formItemMap[field] && formItemMap[field].clearValidate());
}
}
/**
* 重置表单所有值
**/
const reset = function(){
for (const key in props.model) {
props.model[key] = null;
}
// 重新校验
setTimeout(()=>validate()?.catch(err => {}), 0);
}
// 添加子项
const addField = function(item : LayFormItemContext) {
formItems.push(item);
formItemMap[item.prop as string] = item;
}
defineExpose({validate, clearValidate, reset});
provide(layFormKey, reactive({
formItems,
addField,
clearValidate,
validate,
...toRefs(props)
}));
</script>