Обработка watch в vuetify на компоненте v-text-field

Всем привет

Не подскажете, что не так с инпутами от vuetify. Проблема в обработке watch. Во втором поле что бы не писали, значение обрезается, в первом нет. Это баг какой то или так задумано, почему 2 инпута с одинаковым v-model работают по разному?

<template>
<div id="app">
  <v-app>
    {{ count }}
    <v-card class="ma-2 pa-3">
      <v-text-field v-model="foo" outlined></v-text-field>
    </v-card>
    <v-card class="ma-2 pa-3">
      <input class="custom-input" v-model="foo">
    </v-card>
    
    {{ foo }}
  </v-app>
</div>
</template>

<script>

var vm = new Vue({
    el: "#app",
  vuetify: new Vuetify(),
    data() {
    return {
        foo: 'bar',
      count: 0
    }
  },
  watch: {
    foo(oldVal, newVal) {
        if(oldVal) {
        this.foo = oldVal.substr(0, 2);
        
        this.count++
      }
    }
  }
});
</script>

<style>
.custom-input {
  border: 1px solid silver !important;
  border-radius: 5px;
}
</style>

ссылка на код:

https://codepen.io/kalorave/pen/qBNzYZr


Ответы (1 шт):

Автор решения: Николай Парахневич

Выполните вашу функцию из watch после установки данных и обновления DOM компонентом v-text-field, используя метод this.$nextTick(callback), потому как созданное поле ввода, при использовании v-text-field, опирается не на прямое значение value, а на собственное this.lazyValue (обратитесь к исходному коду - https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VTextField/VTextField.ts)

С помощью this.$nextTick(callback) вызов функции callback произойдет при следующем цикле обновления DOM, т.е. после манипуляций с ним от компонента v-text-field.

var vm = new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data() {
    return {
      foo: 'bar',
      count: 0
    }
  },
  watch: {
    foo(oldVal, newVal) {
      this.$nextTick(() => {
        if (oldVal) {
          this.foo = oldVal.substr(0, 2);

          this.count++
        }
      })
    }
  }
});
.custom-input {
  border: 1px solid silver !important;
  border-radius: 5px;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>
<div id="app">
  <v-app>
    {{ count }}
    <v-card class="ma-2 pa-3">
      <v-text-field v-model="foo" outlined></v-text-field>
    </v-card>
    <v-card class="ma-2 pa-3">
      <input class="custom-input" v-model="foo">
    </v-card>

    {{ foo }}
  </v-app>
</div>

→ Ссылка