老师,关于min和max的校验,希望能斧正下
来源:5-7 ValidateForm 组件需求分析
希望林柚一健康快乐成长
2022-03-25
export type ValidationKey = 'email' | 'phone' | 'required' | 'range'
interface RuleProp {
type: ValidationKey;
message?: string;
min?: { message: string, length:number};
max?: { message: string, length:number};
}
interface ResObj {
isValid: boolean;
message: string
}
type Validation = Record<ValidationKey, (param: string, rule: Array<RuleProp>) => ResObj>
// Record是ts中高级类型,可以理解为,定义了一系列的对象,对象的属性值为validtaionKey的值,而属性值则是第二个参数决定的,它可以是对象,联合类型,枚举,函数等等,在这个案例中,他是一个函数,
// 函数有一个参数值是字符串类型,该函数会返回一个布尔值
// 邮箱的正则
const emailReg = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
const phoneReg = /^(?:\+?86)?1(?:3\d{3}|5[^4\D]\d{2}|8\d{3}|7(?:[0-35-9]\d{2}|4(?:0\d|1[0-2]|9\d))|9[0-35-9]\d{2}|6[2567]\d{2}|4(?:(?:10|4[01])\d{3}|[68]\d{4}|[579]\d{2}))\d{6}$/
// 这个地方他导出的就是一个对象,属性为可以,属性值为方法体
export const Validations:Validation = {
email (str, rule) {
const result = { isValid: true, message: '' }
for (let i = 0; i < rule.length; i++) {
if (rule[i].type === 'email') {
result.isValid = emailReg.test(str)
result.message = rule[i].message as string
break
}
}
return result
},
phone (str, rule) {
const result = { isValid: true, message: '' }
for (let i = 0; i < rule.length; i++) {
if (rule[i].type === 'required') {
result.isValid = phoneReg.test(str)
result.message = rule[i].message as string
break
}
}
return result
},
required (str, rule) {
const result = { isValid: true, message: '' }
for (let i = 0; i < rule.length; i++) {
if (rule[i].type === 'required') {
result.isValid = !!str.trim()
result.message = rule[i].message as string
break
}
}
return result
},
range (str: string, rule) {
const newstr = str.trim()
const result = { isValid: true, message: '' }
for (let i = 0; i < rule.length; i++) {
if (rule[i].type === 'range') {
if (rule[i]?.min) {
const nummin = rule[i]?.min?.length as number
if (newstr.length < nummin) {
result.isValid = false
result.message = rule[i]?.min?.message as string
break
}
}
if (rule[i]?.max) {
const nummax = rule[i]?.max?.length as number
if (newstr.length > nummax) {
result.isValid = false
result.message = rule[i]?.max?.message as string
break
}
}
}
}
return result
}
}
老师,上面是我将校验规则单独抽离的ts文件,增加了range校验规则
在ValidateInput.vue中,如下定义
<template>
<div class="validata-input-container pb-3">
<input
v-bind="$attrs"
:class="{'is-invalid': inputRef.error}"
class="form-control"
id="exampleInputEmail1"
:value="inputRef.val"
@input="updateValue"
@blur="validateInput">
<span v-if="inputRef.error" class="invalid-feedback">{{inputRef.message}}</span>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, PropType, onMounted, renderSlot } from 'vue'
import { ValidationKey, Validations } from '../hooks/validation'
import { emitter } from './validateForm.vue'
interface RuleProp {
// ValidationKey是一种类型,可以导入导出使用,那么这里的type就限定了3中,只能是邮箱,手机和必填
type: ValidationKey;
message?: string;
min?: { message: string, length:number};
max?: { message: string, length:number};
}
// export type RulesProp = RuleProp[],这句话的意思是type是类型别名,这句话的意思就是,创建一个类型,这个类型是个数组类型,每个数组成员是RuleProp类型的数据
// export 只是一个关键字,在ts中,类型可以导出和导入,代码实现也可以导出和到入
export type RulesProp = RuleProp[]
export default defineComponent({
props: {
rules: Array as PropType<RulesProp>,
modelValue: String
},
inheritAttrs: false,
setup (props, context) {
// 需要判断用户有没有传入默认的初始值,如果传入了需要显示在页面上
const inputRef = reactive({
val: props.modelValue || '',
error: false,
message: ''
})
const updateValue = (e: KeyboardEvent) => {
// 修改组件的值,实现双向数据绑定
const targetValue = (e.target as HTMLInputElement).value
inputRef.val = targetValue
context.emit('update:modelValue', targetValue)
}
const validateInput = () => {
// 首先判读是否有rules规则
if (props.rules) {
// 判断表单所有的是否都通过校验
for (const rule of props.rules) {
const resultObj = Validations[rule.type](inputRef.val, props.rules)
if (!resultObj.isValid) {
inputRef.error = true
inputRef.message = resultObj.message
return false
}
}
inputRef.error = false
}
}
onMounted(() => {
emitter.emit('form-item-created', inputRef.val)
})
return {
inputRef,
updateValue,
validateInput
}
}
})
</script>
我传入的规则校验是
// 密码的校验规则
const passwordRules: RulesProp = [
{ type: 'required', message: '密码不能为空' },
{ type: 'range', min: { message: '你的密码至少包括六位,不能含有空格', length: 6 }, max: { message: '你的密码至多包括10位,不能含有空格', length: 10 } }
]
但是这样会有一个问题,当密码的校验规则既有min也有max的时候,按照我的写法,他永远只会提示,当前密码长度不能小于6个,当超过10个的时候也是提示这个,因为我在动态判断inputRef.message的时候,用的是三元表达式,这样肯定不对的,我需要一个标识,来判断当前到底是min没有通过,还是max没有通过
我的想法是,range方法返回一个对象类似于{ type :‘min’, flag: true},然后在失焦方法触发的时候,去判断这个类型是啥,然后动态设置inputRef.message的信息,但是会遇到问题,希望老师提供一个解决思路
第二个问题,定义rules类型的时候,因为message变成了一个可选参数,inputRef.message = rule.message ? rule.message : ‘’,这里如果直接赋值会报错,rules上不存在message属性,所有这里我使用了三元表达式,不知道这样写合不合乎规范
2回答
-
张轩
2022-03-29
同学你好
我发现你遇到的大多数都是 ts 问题,而且你学习的很认真,给你点个赞。这里面你遇到的大多数都是类型问题。我这里简单作答一下。
第一:这个文件不应该放到 hooks 当中,它不是一个 hook
关于 ts,这里有个重要的概念是 type guard,类型保护,它会自动缩小范围,你很多问题都是这样出现的。可以使用if 判断将联合类型中的一部分类型排除出去。https://www.typescripttutorial.net/typescript-tutorial/typescript-type-guards/
给你完整的改了一遍,测试完毕,你自己酌情看看,解释了你的疑问,可以好好看下。提交在:
https://gitee.com/wang_shuangqin/those-who-know-also/commit/60fc6b1fd57661db6482ff4dc8a665597b50d7cf
012022-03-29 -
张轩
2022-03-26
同学你好
写的非常认真,很好,给你点个赞,关于你的问题:我认为可以简单这样修改一下,没有测试,只是提供一个思路
range (str: string, min?:minMax, max?: minMax) { // 初始化一个最终结果 const result = { isValid: true, message: '' } const newstr = str.trim() if (min) { // 只可能通过一条条件,或大或小 if (newstr.length < min.length) { result.isValid = false result.message = min.message } } if (max) { if (newstr.length > max.length) { result.isValid = false result.message = max.message } } // 返回这个结果,用 isValid 判断是否通过,用 message 显示错误信息 return result }
032022-03-28
相似问题