使用onBlur触发器时,如何清除模糊验证错误?

时间:2020-11-03 23:54:16

标签: javascript vue.js vuetify.js

我正在开发一个v文本字段,当您按Enter或从文本字段模糊(失去焦点)时,将允许1 + 1之类的简单数学表达式生成2。到目前为止,这是我的代码。

<template>
  <v-text-field
    :rules="rules"
    @blur="compute"
    @keydown.enter="compute"
    v-model="localValue"
    validate-on-blur
  />
</template>

<script>
import { create, all } from 'mathjs'
const math = create(all)

export default {
    name: "NumericTextField",
    props: ["value"],
    data () {
        return {
            localValue: this.value,
        }
    },
    watch: {
        value (v) {
            this.localValue = v
        },
    },
    methods: {
        compute () {
            try {
                const result = math.evaluate(this.localValue)
                this.$emit("input", result)
            } catch (e) {
                console.log("compute error", e)
            }
        },
    },
    computed: {
        rules () {
                return [v => /^([0-9]*[.])?[0-9]+$/.test(v) || "Must be numeric."]
        },
    },
}
</script>

有一个奇怪的行为,就是当我模糊文本字段时,通过跳到下一个文本字段,使validate-on-blur生效,@ blur也会计算结果。验证在这场比赛中获胜,但我仍然看到违规错误,但结果很快变为了应该有效的数字答案。具体来说,我输入1 + 1(由于其中有加号,因此不是数字)。当我按Tab键时,文本框将更改为2(非常好),并且还会出现一个验证错误,抱怨1 + 1不是数字。那是不希望的。如果结果是数字,我希望验证考虑到这一点。但是我不知道如何控制这种比赛状态。

我已经尝试过,并且成功锁定了页面的表单,并通过给我的表单ref并随后在末尾调用this。$ refs.myForm.validate()来显式重新验证字段上的所有表单。计算。但这使我的组件不是真正可重用的,因为它需要了解父窗体。此外,它正在重新评估所有基于模糊的表单验证,如果一页纸很多,我认为这会变得昂贵。

有没有办法控制比赛条件?还是可以解决?

1 个答案:

答案 0 :(得分:1)

我认为没有任何方法可以阻止Vuetify的validate-on-blur首先运行。因此,这是您可以在没有它的情况下进行偷偷摸摸的解决方法。您的模板如下所示:

<template>
  <v-text-field
    :rules="rules"
    @blur="validate"
    @keydown.enter="validate"
    @focus="clearRules"
    @input="clearRules"
    v-model="localValue"
  />
</template>

由于您不会使用validate-on-blur,因此需要手动编写rules的设置和清除代码,否则它们将立即应用于输入。定义一个带有空数组的数据属性:

data() {
  return {
    rules: []
  }
},

每次聚焦字段或发生输入时,rules将被清除。现在所需要做的就是在每个blur / keydown上运行一个validate方法,它将:1)设置规则,2)计算结果:

validate() {
  this.setRules();
  this.compute();
},
setRules() {
  this.rules = [v => /^([0-9]*[.])?[0-9]+$/.test(v) || "Must be numeric."];
},
compute() {
  try {
    const result = math.evaluate(this.localValue)
    this.$emit("input", result)
  } catch(e) {
    console.log("compute error", e)
  }
},

这是工作示例(我使用eval而不是您的mathjs库):

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data() {
    return {
      // ...
      rules: []
    }
  },
  methods: {
    validate() {
      this.setRules();
      this.compute();
    },
    setRules() {
      this.rules = [v => /^([0-9]*[.])?[0-9]+$/.test(v) || "Must be numeric."];
    },
    compute() {
      try {
        this.localValue = eval(this.localValue);
      } catch(e) {
        // console.log("compute error", e)
      }
    },
    clearRules() {
      this.rules = [];
    }
  }
})
<div id="app">
  <v-app>
    <v-text-field
      :rules="rules"
      @blur="validate"
      @keydown.enter="validate"
      @focus="clearRules"
      @input="clearRules"
      v-model="localValue"
      ></v-text-field>
  </v-app>
</div>



<!-- LIBRARIES -->
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>

来自here的想法,适合与blur一起使用。