我创建了一个可组合的 vue 3 来验证不同类型的输入字段。但是,当有多个相同类型的字段时,我确实遇到了问题,好像其中一个有错误会显示在具有相同类型的所有输入下,例如在这个例子中,密码字段 a 我确实有 3 个.
知道如何解决吗?
可组合的验证器:
import { ref } from 'vue'
const errors = ref({ email: '', password: '' })
const validEmail = (email) => {
const regex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return regex.test(email)
}
const types = {
email: 'email',
password: 'password',
}
const validate = (entry, type) => {
if (types[type] === 'email') {
if (!entry) {
errors.value.email = 'Email required.'
} else if (!validEmail(entry)) {
errors.value.email = 'Valid email required.'
} else errors.value.email = ''
}
if (types[type] === 'password') {
if (!entry) {
errors.value.password = 'Password required.'
} else if (entry.length < 8) {
errors.value.password = 'Password should be minimum 8 characters.'
} else errors.value.password = ''
}
}
const useValidator = () => ({ validate, errors })
export default useValidator
我使用它的组件:
<template>
<div
id="account-details"
>
<div class="page px-8 relative">
<title-with-button title="pages.settings.profile" />
<div class="flex flex-col items-center my-12">
<div class="w-full md:w-80">
<div class="flex flex-col">
<label>Email</label>
<input
v-model="email"
type="text"
placeholder="example@we.care"
class="px-2 h-12 my-2 rounded-md"
@input="validate(email, 'email');"
@keyup.enter="handleSubmit()"
>
<div
class="text-red-500 text-sm leading-3 h-3"
>
{{ errors.email }}
</div>
</div>
<div class="flex flex-col">
<label>{{ $t('labels.current_password') }}</label>
<input
v-model="currentPassword"
type="password"
placeholder="Min 8 characters"
class="px-2 h-12 my-2 rounded-md"
@input="validate(currentPassword, 'password')"
@keyup.enter="handleSubmit()"
>
<div
class="text-red-500 text-sm leading-3 h-3"
>
{{ errors.password }}
</div>
</div>
<div class="flex flex-col">
<label>{{ $t('labels.new_password') }}</label>
<input
v-model="newPassword"
type="password"
placeholder="Min 8 characters"
class="px-2 h-12 my-2 rounded-md"
@input="validate(newPassword, 'password')"
@keyup.enter="handleSubmit()"
>
<div
class="text-red-500 text-sm leading-3 h-3"
>
{{ errors.password }}
</div>
</div>
<div class="flex flex-col">
<label>{{ $t('labels.current_password_retype') }}</label>
<input
v-model="newPasswordCopy"
type="password"
placeholder="Min 8 characters"
class="px-2 h-12 my-2 rounded-md"
@input="validate(newPasswordCopy, 'password')"
@keyup.enter="handleSubmit()"
>
<div
class="text-red-500 text-sm leading-3 h-3"
>
{{ errors.password }}
</div>
</div>
</div>
<button
class="cursor-pointer bg-gray-500 text-white text-base border-none no-underline
px-5 py-3 mt-4 rounded-md"
@click="handleSubmit()"
>
{{ $t('button.save') }}
</button>
</div>
</div>
</div>
</template>
<script>
import { ref, computed } from 'vue'
import TitleWithButton from '../components/settings/TitleWithButton.vue'
import useValidator from '../composables/useValidator'
import useUpdateAccount from '../composables/useUpdateAccount'
export default {
name: 'AccountDetails',
components: {
TitleWithButton,
},
setup() {
const email = ref('')
const currentPassword = ref('')
const newPassword = ref('')
const newPasswordCopy = ref('')
const currentUser = JSON.parse(localStorage.getItem('user')).user
email.value = currentUser.email
const { validate, errors } = useValidator()
const { updateAccount, error } = useUpdateAccount()
const inValid = computed(() => {
if ((errors.value.email || errors.value.password)
|| (newPassword.value !== newPasswordCopy.value)) {
return true
} return false
})
const handleSubmit = async () => {
validate(email.value, 'email')
validate(currentPassword.value, 'password')
validate(newPassword.value, 'password')
validate(newPasswordCopy.value, 'password')
if (!inValid.value) {
await updateAccount(email.value, currentPassword.value, newPassword.value)
}
}
return {
email, currentPassword, newPassword, newPasswordCopy, errors, handleSubmit, error, validate,
}
},
}
</script>