Vuelidate 计算的验证 属性
Vuelidate validation of computed property
在我的 Vue 组件中,我有 3 个数字字段,如下所示:
data() {
return {
numberAdults: 0,
numberChildren: 0,
numberInfants: 0,
}
还有一个计算的 属性:
computed: {
numberPersons() {
return this.numberAdults + this.numberChildren + this.numberInfants
},
我想验证是否至少设置了一个人(至少一名成人或一名儿童或一名婴儿),但我无法使其正常工作。这是验证规则:
numberPersons: {
required,
minValue: minValue(1),
},
如果我用三个字段之一更改 numberPersons
,则该字段的验证有效。我认为 Vuelidate 不知何故不知道 numberPersons
是什么,但我不确定如何更改它。
您可以创建一个自定义验证方法,例如 minNumberPersons
,它只验证您计算的 属性 this.numberPersons
:
const minNumberPersons = (value, vm) => {
return vm.numberPersons >= 1;
};
然后,您可以将这些规则应用于不同的模型:
validations: {
numberAdults: { minNumberPersons },
numberChildren: { minNumberPersons },
numberInfants: { minNumberPersons }
}
UX 建议,完全可选:附带说明,因为您将同时验证 3 个字段,所以使用 $v.<field>.$touch()
方法以确保所有 3 个字段的脏状态在其中任何一个更改时都设置为 true
。您可以简单地在您的模板中进行 @input="onInput"
绑定,并将其添加到您的方法中:
onInput() {
this.$v.numberAdults.$touch();
this.$v.numberChildren.$touch();
this.$v.numberInfants.$touch();
},
在此处查看概念验证。我改编自 demo JSFiddle used by the Vuelidate repository.
Vue.use(window.vuelidate.default);
const numberPersons = (value, vm) => {
return vm.numberPersons >= 1;
};
new Vue({
el: "#app",
data: {
numberAdults: 0,
numberChildren: 0,
numberInfants: 0,
},
validations: {
numberAdults: { numberPersons },
numberChildren: { numberPersons },
numberInfants: { numberPersons }
},
computed: {
numberPersons() {
// Converting each to a number using the unary + operator, in case user inputs empty string
return (+this.numberAdults) + (+this.numberChildren) + (+this.numberInfants);
},
},
methods: {
status(validation) {
return {
error: validation.$error,
dirty: validation.$dirty
}
},
// Optional: force validation of all number inputs when any one is changed
onInput() {
this.$v.numberAdults.$touch();
this.$v.numberChildren.$touch();
this.$v.numberInfants.$touch();
},
}
})
body {
background: #fff;
}
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;
}
<!-- Boilerplate adapted from Vuelidate's default demo: https://jsfiddle.net/Frizi/b5v4faqf/ -->
<script src="https://unpkg.com/vuelidate/dist/vuelidate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model.number="$v.numberAdults.$model" :class="status($v.numberAdults)" @input="onInput" type="number">
<input v-model.number="$v.numberChildren.$model" :class="status($v.numberChildren)" @input="onInput" type="number">
<input v-model.number="$v.numberInfants.$model" :class="status($v.numberInfants)" @input="onInput" type="number">
<br />
<br />
Total number of people: <strong>{{ numberPersons }}</strong>
</div>
在我的 Vue 组件中,我有 3 个数字字段,如下所示:
data() {
return {
numberAdults: 0,
numberChildren: 0,
numberInfants: 0,
}
还有一个计算的 属性:
computed: {
numberPersons() {
return this.numberAdults + this.numberChildren + this.numberInfants
},
我想验证是否至少设置了一个人(至少一名成人或一名儿童或一名婴儿),但我无法使其正常工作。这是验证规则:
numberPersons: {
required,
minValue: minValue(1),
},
如果我用三个字段之一更改 numberPersons
,则该字段的验证有效。我认为 Vuelidate 不知何故不知道 numberPersons
是什么,但我不确定如何更改它。
您可以创建一个自定义验证方法,例如 minNumberPersons
,它只验证您计算的 属性 this.numberPersons
:
const minNumberPersons = (value, vm) => {
return vm.numberPersons >= 1;
};
然后,您可以将这些规则应用于不同的模型:
validations: {
numberAdults: { minNumberPersons },
numberChildren: { minNumberPersons },
numberInfants: { minNumberPersons }
}
UX 建议,完全可选:附带说明,因为您将同时验证 3 个字段,所以使用 $v.<field>.$touch()
方法以确保所有 3 个字段的脏状态在其中任何一个更改时都设置为 true
。您可以简单地在您的模板中进行 @input="onInput"
绑定,并将其添加到您的方法中:
onInput() {
this.$v.numberAdults.$touch();
this.$v.numberChildren.$touch();
this.$v.numberInfants.$touch();
},
在此处查看概念验证。我改编自 demo JSFiddle used by the Vuelidate repository.
Vue.use(window.vuelidate.default);
const numberPersons = (value, vm) => {
return vm.numberPersons >= 1;
};
new Vue({
el: "#app",
data: {
numberAdults: 0,
numberChildren: 0,
numberInfants: 0,
},
validations: {
numberAdults: { numberPersons },
numberChildren: { numberPersons },
numberInfants: { numberPersons }
},
computed: {
numberPersons() {
// Converting each to a number using the unary + operator, in case user inputs empty string
return (+this.numberAdults) + (+this.numberChildren) + (+this.numberInfants);
},
},
methods: {
status(validation) {
return {
error: validation.$error,
dirty: validation.$dirty
}
},
// Optional: force validation of all number inputs when any one is changed
onInput() {
this.$v.numberAdults.$touch();
this.$v.numberChildren.$touch();
this.$v.numberInfants.$touch();
},
}
})
body {
background: #fff;
}
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;
}
<!-- Boilerplate adapted from Vuelidate's default demo: https://jsfiddle.net/Frizi/b5v4faqf/ -->
<script src="https://unpkg.com/vuelidate/dist/vuelidate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model.number="$v.numberAdults.$model" :class="status($v.numberAdults)" @input="onInput" type="number">
<input v-model.number="$v.numberChildren.$model" :class="status($v.numberChildren)" @input="onInput" type="number">
<input v-model.number="$v.numberInfants.$model" :class="status($v.numberInfants)" @input="onInput" type="number">
<br />
<br />
Total number of people: <strong>{{ numberPersons }}</strong>
</div>