如何使用VeeValidate验证基于Button构建的自定义Select组件?
当然可以实现!你的问题核心在于ValidationProvider没有和组件的选中值(也就是value prop)建立关联,所以它没法判断当前值是否符合验证规则。下面给你两种可行的解决方案,你可以根据自己的习惯选一种:
方案一:用计算属性代理值(推荐,更贴合VeeValidate的用法)
这种方式通过一个带get/set的计算属性把组件的value prop和ValidationProvider的v-model绑定起来,让ValidationProvider自动跟踪值的变化并触发验证:
- 在BaseSelect.vue的
computed里新增一个代理计算属性:
computed: { // 保留你原来的selected和validationRules selected() { if (this.value === null || !this.items.length) return '' let index = _.findIndex( this.items, (item) => item[this.preferedValue] === this.value ) return this.items[index].name }, validationRules() { if (!this.required) return this.rules return this.rules ? `required|${this.rules}` : 'required' }, // 新增这个代理属性 localValue: { get() { return this.value; }, set(newVal) { this.$emit('input', newVal); } } }
- 修改ValidationProvider标签,绑定
v-model="localValue":
<ValidationProvider tag="div" :vid="name" :mode="validationMode" :rules="validationRules" v-model="localValue" <!-- 这里改成绑定localValue --> v-slot="{ errors }" >
- 把
<li>的点击事件改成直接赋值给localValue:
<li v-for="item in items" :key="item.id" :id="`listbox-item-${item.id}`" role="option" class="text-gray-900 dark:text-white hover:bg-gray-200 dark:hover:bg-gray-700 cursor-default select-none relative py-2 pl-3 pr-9" @click="localValue = item[preferedValue]" <!-- 修改这里 --> >
这样一来,当用户选择选项时,localValue会更新,同时触发input事件同步给父组件的v-model,ValidationProvider也会自动检测到值的变化并执行验证,错误信息会正常显示。
方案二:手动绑定值并触发验证
如果你不想修改现有的emit逻辑,可以直接给ValidationProvider绑定当前的value prop,然后在选择选项时手动触发验证:
- 修改ValidationProvider标签,添加
:value="value"和ref:
<ValidationProvider ref="provider" tag="div" :vid="name" :mode="validationMode" :rules="validationRules" :value="value" <!-- 绑定当前的value prop --> v-slot="{ errors }" >
- 给
<li>的点击事件改成调用一个方法:
<li v-for="item in items" :key="item.id" :id="`listbox-item-${item.id}`" role="option" class="text-gray-900 dark:text-white hover:bg-gray-200 dark:hover:bg-gray-700 cursor-default select-none relative py-2 pl-3 pr-9" @click="handleSelect(item)" <!-- 修改成调用方法 --> >
- 在BaseSelect.vue的
methods里新增这个处理方法:
methods: { // 保留你原来的toggle和close方法 toggle() { this.open = !this.open }, close(e) { if (!this.$el.contains(e.target)) { this.open = false } }, // 新增方法 handleSelect(item) { this.$emit('input', item[this.preferedValue]); // 用$nextTick确保value更新后再验证 this.$nextTick(() => { this.$refs.provider.validate(); }); } }
额外注意点
- 你的
validationRules计算属性逻辑是正确的,能根据required状态生成对应规则,这部分不需要改动。 - 父组件的
BaseForm通过ValidationObserver已经能自动收集所有字段的验证状态,提交表单时会触发整体验证,这部分也无需调整。 - 当用户未选择任何选项时,
value为null,required规则会触发,错误信息会显示在你写的<small>标签中。
两种方案都能解决你的验证问题,方案一更符合Vue和VeeValidate的双向绑定习惯,推荐使用~
内容的提问来源于stack exchange,提问作者Yura
相关产品推荐
相关产品推荐

