如何仅使用 Vuelidate 验证 onblur?
How to validate only onblur with Vuelidate?
从我的父组件,我以这种方式调用我的自定义输入子组件:
<custom-input
v-model="$v.form.userName.$model"
:v="$v.form.userName"
type="text"
/>
这是我的自定义输入组件:
<template>
<input
v-bind="$attrs"
:value="value"
v-on="inputListeners"
:class="{ error: v && v.$error }"
>
</template>
<script>
export default {
inheritAttrs: false,
props: {
value: {
type: String,
default: ''
},
v: {
type: Object,
default: null
}
},
computed: {
inputListeners () {
const vm = this
return Object.assign({},
this.$listeners,
{
input (event) {
vm.$emit('blur', event.target.value)
}
}
)
}
}
}
</script>
这会从输入字段中输入的第一个字符触发验证错误(这可以说是糟糕的用户体验,所以我真的不明白为什么这是默认行为)。
无论如何,如何仅在 blur
事件上触发此类错误?
这不是默认行为 - 这是您的代码!
只有在通过调用 $touch
method. But when you are using $model
property ($v.form.userName.$model
) for v-model
, it calls $touch
automatically - docs
将字段标记为脏后,Vuelidate 才会验证(并引发错误)
所以要么不要使用 $model
进行绑定,而是在 blur
事件中(或任何你想要的时候)自己调用 $touch
或者您可以尝试使用 .lazy
modifier on v-model but that is supported only on native input elements (support for custom components is long time request)
下面的例子展示了如何自己实现它....
Vue.use(window.vuelidate.default)
Vue.component('custom-input', {
template: `
<input
v-bind="$attrs"
:value="value"
v-on="inputListeners"
:class="status(v)"
></input>
`,
inheritAttrs: false,
props: {
value: {
type: String,
default: ''
},
v: {
type: Object,
default: null
},
lazy: {
type: Boolean,
default: false
}
},
computed: {
inputListeners() {
const listeners = { ...this.$listeners }
const vm = this
const eventName = this.lazy ? 'change' : 'input'
delete listeners.input
listeners[eventName] = function(event) {
vm.$emit('input', event.target.value)
}
return listeners
}
},
methods: {
status(validation) {
return {
error: validation.$error,
dirty: validation.$dirty
}
}
}
})
const { required, minLength } = window.validators
new Vue({
el: "#app",
data: {
userName: ''
},
validations: {
userName: {
required,
minLength: minLength(5)
}
}
})
input {
border: 1px solid silver;
border-radius: 4px;
background: white;
padding: 5px 10px;
}
.dirty {
border-color: #5A5;
background: #EFE;
}
.dirty:focus {
outline-color: #8E8;
}
.error {
border-color: red;
background: #FDD;
}
.error:focus {
outline-color: #F99;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vuelidate/dist/vuelidate.min.js"></script>
<script src="https://unpkg.com/vuelidate/dist/validators.min.js"></script>
<div id="app">
<custom-input v-model="$v.userName.$model" :v="$v.userName" type="text" lazy></custom-input>
<pre>Model: {{ userName }}</pre>
<pre>{{ $v }}</pre>
</div>
尝试从 blur
事件的处理程序发出输入事件,因此:
而不是:
v-on="inputListeners"
设置
@blur="$emit('input', $event.target.value)"
从我的父组件,我以这种方式调用我的自定义输入子组件:
<custom-input
v-model="$v.form.userName.$model"
:v="$v.form.userName"
type="text"
/>
这是我的自定义输入组件:
<template>
<input
v-bind="$attrs"
:value="value"
v-on="inputListeners"
:class="{ error: v && v.$error }"
>
</template>
<script>
export default {
inheritAttrs: false,
props: {
value: {
type: String,
default: ''
},
v: {
type: Object,
default: null
}
},
computed: {
inputListeners () {
const vm = this
return Object.assign({},
this.$listeners,
{
input (event) {
vm.$emit('blur', event.target.value)
}
}
)
}
}
}
</script>
这会从输入字段中输入的第一个字符触发验证错误(这可以说是糟糕的用户体验,所以我真的不明白为什么这是默认行为)。
无论如何,如何仅在 blur
事件上触发此类错误?
这不是默认行为 - 这是您的代码!
只有在通过调用 $touch
method. But when you are using $model
property ($v.form.userName.$model
) for v-model
, it calls $touch
automatically - docs
所以要么不要使用 $model
进行绑定,而是在 blur
事件中(或任何你想要的时候)自己调用 $touch
或者您可以尝试使用 .lazy
modifier on v-model but that is supported only on native input elements (support for custom components is long time request)
下面的例子展示了如何自己实现它....
Vue.use(window.vuelidate.default)
Vue.component('custom-input', {
template: `
<input
v-bind="$attrs"
:value="value"
v-on="inputListeners"
:class="status(v)"
></input>
`,
inheritAttrs: false,
props: {
value: {
type: String,
default: ''
},
v: {
type: Object,
default: null
},
lazy: {
type: Boolean,
default: false
}
},
computed: {
inputListeners() {
const listeners = { ...this.$listeners }
const vm = this
const eventName = this.lazy ? 'change' : 'input'
delete listeners.input
listeners[eventName] = function(event) {
vm.$emit('input', event.target.value)
}
return listeners
}
},
methods: {
status(validation) {
return {
error: validation.$error,
dirty: validation.$dirty
}
}
}
})
const { required, minLength } = window.validators
new Vue({
el: "#app",
data: {
userName: ''
},
validations: {
userName: {
required,
minLength: minLength(5)
}
}
})
input {
border: 1px solid silver;
border-radius: 4px;
background: white;
padding: 5px 10px;
}
.dirty {
border-color: #5A5;
background: #EFE;
}
.dirty:focus {
outline-color: #8E8;
}
.error {
border-color: red;
background: #FDD;
}
.error:focus {
outline-color: #F99;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vuelidate/dist/vuelidate.min.js"></script>
<script src="https://unpkg.com/vuelidate/dist/validators.min.js"></script>
<div id="app">
<custom-input v-model="$v.userName.$model" :v="$v.userName" type="text" lazy></custom-input>
<pre>Model: {{ userName }}</pre>
<pre>{{ $v }}</pre>
</div>
尝试从 blur
事件的处理程序发出输入事件,因此:
而不是:
v-on="inputListeners"
设置
@blur="$emit('input', $event.target.value)"