抽离了验证逻辑,可用于登录、表单验证等场景
import {LoadAttributeByPath} from "../LoadAttributeByPath";
import {Ref} from "vue";
type ValidationOptions = {
base?: string[]
}
class ValidatorUnit<SourceType> {
targetName: keyof SourceType;
validateMethod: (val: any, sourceData?: SourceType) => boolean;
constructor(targetName: any, validateMethod: (val: any, sourceData?: SourceType) => boolean) {
this.targetName = targetName;
this.validateMethod = validateMethod;
}
}
export class Validator<SourceType> {
sourceData: SourceType = null as unknown as SourceType;
refSource: Ref<SourceType> = null as unknown as Ref<SourceType>;
validationList: Array<ValidatorUnit<SourceType>> = [];
options?: ValidationOptions
constructor(sourceData: Ref<SourceType>, options?: ValidationOptions) {
if (options) {
this.options = options;
}
this.refSource = sourceData;
}
bind(propName: keyof SourceType, validator: (val: any, sourceData?: SourceType) => boolean) {
this.validationList.push(new ValidatorUnit(propName, validator));
return this;
}
useTarget(newSource: SourceType) {
if (this.options?.base) {
this.sourceData = LoadAttributeByPath(newSource, this.options.base) as SourceType;
} else {
this.sourceData = newSource;
}
}
validate(): boolean {
this.useTarget(this.refSource.value)
// every: 检测数组是否每个都符合条件
return this.validationList.every(unit => unit.validateMethod(this.sourceData[unit.targetName], this.sourceData));
}
}
export function useValidation<SourceType>(sourceData: Ref<SourceType>, options?: ValidationOptions) {
return new Validator<SourceType>(sourceData, options);
}
但使用的时候要注意,构造函数要传入一个Ref<T>
类型
<script setup lang="ts">
import {ref, reactive, PropType, shallowReactive, watch, toRef} from "vue";
import {UserInfo} from "../type/UserInfo";
import {useValidation} from "../utils/use/useValidation";
const props = defineProps({
userInfo: {
type: Object as PropType<UserInfo>,
default: new UserInfo()
}
})
const UserValidation = useValidation(toRef(props, 'userInfo'))
.bind('username', (val, instance) => {
if (val.length < 3) {
validationResult.value = `name must be at least 3 characters(${JSON.stringify(instance)})`;
return false;
}
return true;
})
.bind('password', (val, instance) => {
if (val < 18) {
validationResult.value = `password must be greater than 18(${JSON.stringify(instance)})`;
return false;
}
return true;
});
const validationResult = ref('ve here')
function validate() {
if (UserValidation.validate()) {
validationResult.value = 'success';
}
}
</script>
<template>
<div class="SubComponent__container">
{{ props.userInfo }}
<el-input v-model="props.userInfo.username"/>
<el-input v-model="props.userInfo.password"/>
<el-button @click="validate">验证</el-button>
{{ validationResult }}
</div>
</template>
<style lang="scss" scoped>
.SubComponent__container {
height: 70%;
display: flex;
align-items: center;
justify-content: center;
.el-input {
width: 200px;
}
}
</style>