当一个值更改时,我试图验证两个输入字段。这是必需的,因为否则这两个字段之间的验证将无法正常进行。
我创建了一个示例来重现该问题,该html代码应该可以自我解释
<div id="app">
<v-app id="inspire">
<v-text-field
:value="values[0]"
:rules="firstRules"
@input="setFirstValue"
></v-text-field>
<v-text-field
:value="values[1]"
:rules="secondRules"
@input="setSecondValue"
></v-text-field>
</v-app>
</div>
请注意,v-model
是不可能的,因为此组件将值作为prop
并通过发出更新事件将更新后的值传递回父级。
vue实例:
new Vue({
el: '#app',
data () {
return {
values: [5345, 11],
firstRules: [true],
secondRules: [true]
}
},
created: function () {
this.setFirstValue(this.values[0])
this.setSecondValue(this.values[1])
},
computed: {
firstValidation: function () {
return [value => value.length < this.values[1].length || "Must have less characters than second value"]
},
secondValidation: function () {
return [value => value.length > this.values[0].length || "Must have more characters than first value"]
}
},
methods: {
setFirstValue: function (newValue) {
this.values[0] = newValue
this.firstRules = this.validateValue(this.values[0], this.firstValidation)
this.secondRules = this.validateValue(this.values[1], this.secondValidation)
},
setSecondValue: function (newValue) {
this.values[1] = newValue
this.secondRules = this.validateValue(this.values[1], this.secondValidation)
this.firstRules = this.validateValue(this.values[0], this.firstValidation)
},
validateValue: function (value, rules) {
for (const rule of rules) {
const result = rule(value)
if (typeof result === 'string') {
return [result]
}
}
return [true]
}
}
})
在“开始”时,规则返回有效状态,但是我想在加载组件时(创建的钩子?)验证两个字段以立即更新此状态。
我必须将验证规则应用于计算所得的属性,因为它们必须访问当前值。否则,他们将验证旧值。
每个输入事件将同时验证两个字段并更新规则状态。
我创建了一个在此处玩耍的示例
https://codepen.io/anon/pen/OeKVME?editors=1010
不幸的是出现了两个问题:
当一个字段更新时,如何为两个字段设置验证?
答案 0 :(得分:2)
似乎您在想太多事情。
默认情况下,仅当绑定到该输入的值更改时,才会触发vuetify输入的验证逻辑。为了触发其他输入的验证,您可以将两个输入都包装在v-form
组件中,并为其提供一个ref
属性。这样,您将可以访问该组件的validate
方法,该方法将触发表单内任何输入的验证逻辑。
模板看起来像这样:
<v-form ref="form">
<v-text .../>
<v-text .../>
</v-form>
并在脚本中触发验证:
mounted() {
this.$refs.form.validate();
}
以上内容将在安装组件时验证表单,但是每当输入值发生变化时,您还需要触发两个输入的验证。为此,您可以向values
添加观察者。但是,您需要在Vue更新DOM以反映validate
中的更改之后调用表单的values
方法。
要执行此操作,请将呼叫包装在this.$nextTick
呼叫中:
watch: {
values() {
this.$nextTick(() => {
this.$refs.form.validate();
});
}
}
或使用async
function和await this.$nextTick
:
watch: {
async values() {
await this.$nextTick();
this.$refs.form.validate();
}
}
因此,当组件初始化以及每一个值改变时,验证都会触发两个输入。但是,如果您希望将验证呼叫放在一个位置而不是同时放在mounted
钩子和values
观察者中,则可以使观察者immediate
并摆脱呼叫mounted
钩子。
所以这是最后一个例子:
watch: {
immediate: true,
async handler() {
await this.$nextTick();
this.$refs.form.validate();
}
}
因此,现在验证逻辑将在预期的时间触发,但是您的验证逻辑仍然存在一个问题。组件初始化时,会将values
数据属性设置为Number
类型值的数组,这些类型值没有length
属性。因此,例如,如果您仅将第一个输入更改为"5"
,而第二个输入仍为11
,则(11).length
为undefined
,而"5".length < undefined
为{ {1}}。
无论如何,在比较它们的长度之前,您需要更改要与字符串比较的值。像这样:
false
最后,因为您可以在表单上动态调用value => (value + '').length < (this.values[1] + '').length
,所以有机会降低组件的许多复杂性。
这是简化版:
validate
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data() {
return {
values: [5345, 11]
}
},
computed: {
rules() {
const valid = (this.values[0] + '').length < (this.values[1] + '').length;
return {
first: [() => valid || "Must have less characters than second value"],
second: [() => valid || "Must have more characters than first value"]
};
}
},
watch: {
values: {
immediate: true,
async handler() {
await this.$nextTick();
this.$refs.form.validate();
}
}
}
})