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

我创建了一个例子来重现这个问题,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]
    }
  }
})

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

我必须将验证规则放入计算(computed)属性,因为它们必须访问当前值.否则他们会验证旧的价值观.

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

我在这里创建了一个例子

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

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

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

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

推荐答案

看来你想得太多了.

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

模板的外观如下所示:

<v-form ref="form">
  <v-text .../>
  <v-text .../>
</v-form>

要在脚本中触发验证,请执行以下操作:

mounted() {
  this.$refs.form.validate();
}

上述内容将在安装组件时对表单进行验证,但您还需要在任何一个输入的值发生变化时触发对这两个输入的验证.为此,您可以将一个观察者添加到values.但是,在Vue更新DOM以反映values中的更改后,需要调用表单的validate方法.

要做到这一点,请将通话包装为this.$nextTick次通话:

watch: {
  values() {
    this.$nextTick(() => {
      this.$refs.form.validate();
    });
  }
}

或者使用async functionawait this.$nextTick:

watch: {
  async values() {
    await this.$nextTick();
    this.$refs.form.validate();
  }
}

因此,当组件初始化时,以及任何一个值发生变化时,都会触发两个输入的验证.但是,如果您希望将验证调用保留在一个位置,而不是同时保留在mounted钩子和values观察程序中,那么您可以将观察程序设置为immediate,并go 掉mounted钩子中的调用.

最后一个例子是:

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

所以现在验证逻辑会在预期的时间触发,但您的验证逻辑仍然存在一个问题.当您的组件初始化时,values data属性被设置为Number个类型值的数组,这些值没有length属性.例如,如果你把第一个输入改为"5",第二个输入仍然是11,那么(11).lengthundefined"5".length < undefinedfalse.

无论如何,在比较字符串长度之前,需要更改与字符串比较的值.比如:

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();
      }
    }
  }
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>

<div id="app">
  <v-app id="inspire">
    <v-form ref="form">
      <v-text-field v-model="values[0]" :rules="rules.first"></v-text-field>
      <v-text-field v-model="values[1]" :rules="rules.second"></v-text-field>
    </v-form>
  </v-app>
</div>

Vue.js相关问答推荐

如何禁用Vuetify v—stepper操作按钮

Vutify-v-工具提示-不使用键盘轻击按钮显示

在vuejs中使用表单追加时如何使用布尔值

Vue 2 如何在全局函数中返回观察者

使用 Vue.js 清除数组内容和react性问题

在 Ajax 函数中访问 Vue.js 组件属性

Vue-tables-2(vuex)react性不起作用

Vuetify 置顶工具栏

如何将 axios/axios 拦截器全局附加到 Nuxt?

为什么 Vue 路由/Webpack 开发服务器现在在页面刷新时显示无法获取/路径?

如何为 Vue 项目设置 lint-staged?

vuejs中通过变量动态调用方法

Vuetify - 如何在 v-data-table 中单击时突出显示行

Vuetify 2 个工具栏和 1 个导航抽屉,navigation drawer导航抽屉上方有 1 个工具栏

安装后运行computed计算函数

是否有 v-cloak 逆?

无法访问手表处理程序 vuejs 中的数据变量

VueJS 复选框更新

IOS在输入焦点上显示键盘

Vuetify v-data-table 固定标题不起作用