javascript - 输入时表单输入未得到验证 (@input),只有 @blur 有效
问题描述
我正在使用带有输入数据验证的组合框(Vuelidate):
<template>
<v-combobox
clearable
v-model="surname"
:items="commonSurnames"
label="Surname"
placeholder="Type in the surname"
class="pt-5 pb-5"
:error-messages="surnameErrors"
@input="$v.surname.$touch()"
@blur="$v.surname.$touch()">
</v-combobox>
</template>
<script>
import { validationMixin } from 'vuelidate'
import { required, maxLength } from 'vuelidate/lib/validators'
export default {
mixins: [validationMixin],
validations: {
surname: {
required,
maxLength: maxLength(30),
validSurname(surname) {
return (
/^[a-zA-Z]-?*.+$/.test(surname)
)
}
},
name: 'Surnames',
data() {
return {
surname: '',
[...]
},
methods: {
[...]
},
computed: {
surnameErrors() {
const errors = []
if (!this.$v.surname.$dirty) return errors
!this.$v.surname.validSurname && errors.push('Format must be like: Smith or Smith-Wesson')
!this.$v.surname.maxLength && errors.push('Surname must be at most 30 characters long.')
!this.$v.surname.required && errors.push('Surname is required.')
return errors
}
}
</script>
组件版本:
"dependencies": {
"@vue/compiler-sfc": "^3.0.0",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vuelidate": "^0.7.5",
"vuetify": "^2.2.11"
},
我想我在Vuetify 文档中做了所有事情,但是我的表单得到的验证与文档中的内容有点不同:我可以超过 30 个字符的限制,而不会在输入时收到通知。我只有在输入失去焦点时才知道。RegEx 验证的情况相同:接受任何值而没有错误通知。如果该值无效,我会在离开输入字段时收到通知。
从文档中复制示例时我是否遗漏了什么,或者@input
监听器工作不正确?还是v-combobox
不能以这种方式验证?
解决方案
我曾经有一个组件包装器v-combobox
,v-autocomplete
并且v-select
(是的,单个多用途包装器)。我建议在包装器中使用下面的代码,以避免复制粘贴修复/解决方法。
一般来说,解决方法需要查找 Vuetify 源。这导致了操纵和errorBucket
倾听。valid
@update:search-input
此外,您可能想要发出'input'
. 它需要一个小的调整来抑制传播到v-combobox
值,否则它会破坏自动完成行为。因此if (this.search) { return; }
完整示例:Codepen
Vue.component(
'my-combobox', {
template: `
<v-combobox
ref="combobox"
outlined dense
v-model="selection"
v-bind="{ ...$attrs, items, rules: validationRules }"
v-on="$listeners"
@update:search-input="onSearch"
@focus="touched = true"></v-combobox>
`,
props: {
value: String,
items: Array,
required: Boolean,
rules: Array,
},
data() {
return {
selection: null,
search: null,
touched: false,
};
},
computed: {
validationRules() {
return [
...(this.rules || []),
(v) => !this.required || (v?.length ?? 0) > 0 || 'Value is required',
];
},
},
methods: {
onSearch(v) {
if (!this.touched) return;
this.search = v;
const $self = this.$refs.combobox;
$self.errorBucket = this.validationRules.filter(f => f(v) !== true);
$self.valid = $self.errorBucket.length === 0;
this.$emit('input', v);
},
},
watch: {
selection: {
handler(v) {
this.$emit('input', v);
},
},
value: {
immediate: true,
handler(v) {
if (this.search) { return; }
this.selection = v;
},
},
},
});
推荐阅读
- android - 像 Snapchat 回忆一样向上滑动
- c# - 使用 Azure KeyVault 和 Visual Studio 管理用户机密不适用于 ASP .Net Core
- amazon-redshift - 使用临时表缓存查询结果
- python - 如何在 QTableWidget 中绘图
- lua - lua:如何在 __tostring 元方法中获取原始字符串?
- python - 为什么在使用 ImageDataGenerator 和 .flow() 时有些图像可以正确保存而有些则不能?
- perl - 从模板工具包中的代码引用调用
- tensorflow - How to connect RNN at the end of a CNN to use to train video frames?
- r - 如何在ggplot2中制作单个堆叠条形图
- java - 如何为输入地址制作好的editText?