如何在更新时验证两个输入字段

14 vue.js vuetify.js

当一个输入字段更改其值时,我试图验证两个输入字段。这是必需的,否则这两个字段之间的验证将无法正常工作。

我创建了一个示例来重现问题,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>
Run Code Online (Sandbox Code Playgroud)

重要的是要注意 av-model是不可能的,因为该组件将值作为 a 接收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]
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

在“开始”时,规则返回一个有效状态,但我想在加载组件(创建钩子?)时验证这两个字段以立即更新此状态。

我必须将验证规则放在计算属性中,因为它们必须访问当前值。否则他们会验证旧值。

每个输入事件将验证两个字段并更新规则状态。

我创建了一个例子在这里玩

https://codepen.io/anon/pen/OeKVME?editors=1010

不幸的是出现了两个问题:

  • 字段在开始时不直接验证
  • 将一个输入字段更改为有效状态时,规则仍将返回错误消息

当一个字段更新时,如何为两个字段设置验证?

tha*_*ksd 16

看来你想多了。

默认情况下,vuetify 输入的验证逻辑仅在绑定到该输入的值更改时触发。为了触发对另一个输入的验证,您可以将两个输入包装在一个v-form组件中并为其指定一个ref属性。这样,您就可以访问该组件的validate方法,这将触发表单内任何输入的验证逻辑。

模板看起来像这样:

<v-form ref="form">
  <v-text .../>
  <v-text .../>
</v-form>
Run Code Online (Sandbox Code Playgroud)

并在您的脚本中触发验证:

mounted() {
  this.$refs.form.validate();
}
Run Code Online (Sandbox Code Playgroud)

以上将在组件安装时验证表单,但您还需要在任一输入的值更改时触发对两个输入的验证。为此,您可以向values. 但是,您需要validate在 Vue 更新 DOM 以反映values.

为此,请将调用包装在调用中this.$nextTick:

watch: {
  values() {
    this.$nextTick(() => {
      this.$refs.form.validate();
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

或者使用async函数和await this.$nextTick:

watch: {
  async values() {
    await this.$nextTick();
    this.$refs.form.validate();
  }
}
Run Code Online (Sandbox Code Playgroud)

所以现在验证将在组件初始化时以及任何一个值更改时触发两个输入。但是,如果您更喜欢将验证调用保留在一个位置,而不是同时保留在mounted挂钩和values观察者中,则可以创建观察者immediate并摆脱mounted挂钩中的调用。

所以这是最后一个例子:

watch: {
  immediate: true,
  async handler() {
    await this.$nextTick();
    this.$refs.form.validate();
  }
}
Run Code Online (Sandbox Code Playgroud)

所以现在验证逻辑在预期的时候触发,但你的验证逻辑仍然存在一个问题。当您的组件初始化时,values数据属性被设置为一个Number没有length属性的类型值数组。因此,例如,如果您仅将第一个输入更改为"5"并且第二个输入仍然为11,则(11).lengthisundefined和"5".length < undefinedis false。

无论如何,在比较字符串的长度之前,您需要更改要与字符串进行比较的值。像这样的东西:

value => (value + '').length < (this.values[1] + '').length
Run Code Online (Sandbox Code Playgroud)

最后,因为您能够动态调用validate表单,所以有机会降低组件的大部分复杂性。

这是一个简化版本:

<v-form ref="form">
  <v-text .../>
  <v-text .../>
</v-form>
Run Code Online (Sandbox Code Playgroud)
mounted() {
  this.$refs.form.validate();
}
Run Code Online (Sandbox Code Playgroud)

  • 这样会不会遇到这样的问题:如果表单上还有其他输入字段用户尚未输入数据,这些字段的验证也会被触发;导致用户体验不太理想。有没有办法只在特定字段而不是整个表单上触发验证? (5认同)