Как использовать v-модель и вычисляемые свойства в полях ввода? - PullRequest
0 голосов
/ 16 апреля 2020

У меня есть простой компонент с 2 полями ввода:

<template>
    <div>
        <input type="text" v-model="name">
        <input type="text" v-model="alias">
    </div>
</template>

<script>
    export default {
        data() {
            return {
                name: "",
                alias: ""
            }
        }
    }
</script>

Я хочу автоматически вставить значение модели name в поле alias, если поле alias пусто. Если он не пустой, я хочу использовать его собственное значение.

Вот моя попытка:

<template>
    <div>
        <input type="text" v-model="name">
        <input type="text" v-model="alias">
    </div>
</template>

<script>
    export default {
        data() {
            return {
                name: "",
                alias: ""
            }
        },
        computed: {
            alias: {
                get: function() {
                    if (this.alias.length < 1) {
                        return this.name
                    } else {
                        return this.alias
                    }
                },
                set: function(newValue) {
                    this.alias = newValue
                }
            }
        }
    }
</script>

Проблема в том, что alias не получает фактическое значение в alias свойство, если я что-то наберу в поле name. Я могу видеть это только визуально - но это не имеет значения. Однако, если я введу в поле alias, оно будет обновлено должным образом.

Чего мне здесь не хватает и как мне сделать так, как я хочу?

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Во-первых, вы не можете иметь вычисляемое свойство и свойство данных с тем же именем. Поскольку как вычисляемые свойства, так и свойства данных заканчиваются как свойства одного и того же объекта состояния, одно перезапишет другое.

Во-вторых, и я думаю, что вы сделали это из-за первой точки в вычисленном alias геттере, Вы снова ссылаетесь на alias, который, по сути, ссылается на себя, и похоже, что он может дать некоторые противоречивые возвращаемые значения.

Я могу придумать два решения вашей проблемы:

1) Используйте наблюдателя на name:

Создайте функцию наблюдателя для name и установите для нее this.alias то же значение, что и name, когда alias пусто, или если оно совпадает с предыдущим значением имени.

<script>
    export default {
        data: () => ({
            name: "",
            alias: ""
        }),
        watch: {
            name(newVal, oldVal) {
                if (!this.alias || this.alias === oldVal) {
                    this.alias = newVal;
                }
            }
        }
    }
</script>

2) Используйте явные привязки :value и @change / @keyup при вводе имени:

v-model - это удобный метод, который устанавливает оба этих параметра для вас, но в вашем случае вы хотите добавить еще несколько логин c в обработчик изменений, который просто устанавливает значение свойства состояния.

<template>
    <div>
        <input
          type="text"
          :value="name"
          @keyup="onNameInput"
        />
        <input type="text" v-model="alias">
    </div>
</template>

<script>
    export default {
        data: () => ({
            name: "",
            alias: ""
        }),
        methods: {
            // Check and set both values on name input events
            onNameInput(e) {
                if (!this.alias || this.alias === this.name) {
                    this.alias = e.target.value;
                }
                this.name = e.target.value;
            }
        }
    }
</script>
1 голос
/ 16 апреля 2020

Computed не будет работать, потому что оно должно рассматриваться как неизменяемое.

Кроме того, поскольку модель будет обновляться на каждом входе, часы также не будут работать, они будут брать только первый символ то, что вы вводите, если только оно не заполнено предварительно.

Вот как я бы это сделал, просто добавьте событие @blur на ввод имени, а затем запустите метод, который заполняет псевдоним, если он пустой, и псевдоним в случае, если они опустошают его.

Тот же самый метод можно использовать в смонтированном, если вы предварительно заполнили модели, или вы можете посмотреть его.

{
  template: `
  <div>
     <input type="text" v-model="name" @blur="setAlias()">
      <input type="text" v-model="alias" @blur="setAlias()">
  </div>
  `,
  data() {
    return {
      name: '',
      alias: ''
    }
  },
  methods: {
    setAlias() {
      if (this.alias === '') {
        this.alias = this.name
      }
    }
  }
}

...