自定义vee-validate组件v-model赋值时meta.valid为false问题
问题根因
两个异常同源,都是useField配置和组件绑定逻辑错误,导致外部赋值无法同步到vee-validate内部状态,校验逻辑不触发:
useField的valueProp配置传了静态的props.modelValue初始值,该配置要求传入对应prop的键名字符串,而非prop值;同时缺少syncVModel配置,外部修改modelValue时,vee-validate内部的inputValue、校验状态完全感知不到变化- 输入框的
:value错误绑定到了外部传入的modelValue,没有绑定vee-validate托管的响应式值inputValue,内部状态变化无法同步到视图 - 程序赋值(created/watch中修改值)默认不会触发校验,需要开启值更新自动校验配置
onInput中直接传入事件对象给handleChange的写法存在取值不稳定问题
修复方案
- 修正
useField配置,开启v-model双向同步、值更新自动校验,valueProp传入prop名的字符串 - 将输入框的value绑定目标改为
inputValue - 优化输入事件逻辑,直接取输入值同步状态,不需要额外手动在生命周期、watcher中给
inputValue赋值,配置正确后外部修改modelValue会自动同步内部状态并触发校验
修正后的完整组件代码:
<template> <div class="TextInput" :class="{ 'has-error': !!errorMessage, 'success': meta.valid }" > <label :for="name">{{ label }}</label> <input :name="name" :id="name" :type="type" :placeholder="placeholder" :value="inputValue" :class="inputClass" @input="onInput($event)" @blur="handleBlur" /> <p class="help-message" v-show="errorMessage || meta.valid"> {{ errorMessage || successMessage }} </p> </div> </template> <script> import { useField } from "vee-validate"; export default { props: { type: { type: String, default: "text", }, name: { type: String, required: true, }, label: { type: String, required: false, }, successMessage: { type: String, default: "", }, placeholder: { type: String, default: "", }, modelValue: { type: [String, Number], default: "" }, inputClass: { type: String, default: "", }, }, setup(props, {emit}) { const { value: inputValue, errorMessage, handleBlur, meta, } = useField(props.name, undefined, { initialValue: props.modelValue, valueProp: 'modelValue', // 传入prop名称字符串,不是静态值 syncVModel: true, // 开启和外层v-model的双向同步 validateOnValueUpdate: true // 值变更时自动触发校验 }); const onInput = (event) => { const inputVal = event.target.value inputValue.value = inputVal emit('update:modelValue', inputVal) } return { onInput, handleBlur, errorMessage, inputValue, meta, }; } }; </script>
补充说明
- 已移除代码中无用的
valueprop,避免和v-model逻辑冲突 - 如果需要在输入失焦后才触发校验,可以把
validateOnValueUpdate设为false,保留handleBlur的触发逻辑即可 - 目前
useField第二个校验规则参数传的是undefined,如果要自定义校验规则,直接在该位置传入校验函数或校验规则即可,不传入的话非空值默认会判定为valid
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

