Измените связанную v-модель, изменив значение на входе

Я пытаюсь реализовать экранную клавиатуру для ввода чисел в различные поля ввода. В реальном проекте их несколько десятков. Я сохраняю активное поле через фокус, и когда я нажимаю на число, оно добавляется в конец значения поля. Но когда я меняю значение ввода, значение связанной v-модели не меняется. Хотя, когда захожу с обычной клавиатуры, все меняется нормально. прилагаю пример кода

<template>
    <p>xSize</p>
    <input v-model = "xSize">
    <p>ySize</p>
    <input v-model = "ySize">
    <div class = "keyboard">
        <button v-for = "i in [1,2,3,4,5,6,7,8,9,0]" class = "key" :key = "i" @click = "addChar(i)">{{i}}</button>
    </div>
    <p>xSize = {{xSize}}</p>
    <p>ySize = {{ySize}}</p>
    <div class = "test-box" v-bind:style = "{width: this.xSize + 'px', height: this.ySize + 'px'}"></div>


</template>

<script>
export default {
  data: function () {
    return {
      xSize: 50,
      ySize: 50,
      activeElement: null
    }
  },
  props: {

  },
  created() {
    document.addEventListener('focusin', this.focusChanged)
  },
  beforeUnmount() {
    document.removeEventListener('focusin', this.focusChanged)
  },
  methods: {
    focusChanged: function (event) {
      const el = event.target
      if (el.type === "text") {
        if (this.activeElement !== el && this.activeElement !== null) {
          this.activeElement.style.background = "white";
        }

        this.activeElement = el
        this.activeElement.style.background = "red";
      }
    },
    addChar: function (char) {
      if (this.activeElement !== null) {
        this.activeElement.value += char
      }
    }

  }
}
</script>

<style scoped>
    .keyboard {
      display: flex;
    }
    .key {
      margin: 3px;
      width: 30px;
      height: 30px;
      border: 2px black ridge;
    }

    .test-box {
      border: 2px black ridge;
      background: red;
      margin: 15px;
    }
</style>

Пример

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
59
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

попробуйте проверить что-то вроде:

<input v-model = "xSize" @input = "updateSize('xSize', $event.target.value)">

  • @input событие в полях ввода, чтобы гарантировать, что любое изменение входного значения фиксируется и обрабатывается методом updateSize,
  • метод updateSize вызывается с соответствующим типом размера (xSize или ySize) и новым значением. Этот метод обновляет соответствующее свойство в экземпляре Vue.

Спасибо за ответ. Увы, событие @input не срабатывает при нажатии клавиш.

Ruslan54 02.08.2024 09:39

Потому что вы изменили только значение элемента, а не реагирующие данные в данных.

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

Ruslan54 02.08.2024 12:41

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

jack ma 05.08.2024 05:32

Пожалуйста, взгляните на следующий пример (вы можете использовать событие @focus и преобразовать код в API-интерфейс опций, если вам так нравится :))

const { ref, computed } = Vue
const app = Vue.createApp({
  setup() {
    const xSize = ref(50)
    const ySize = ref(50)
    const activeElement = ref('x')
    const operation = ref('+')
    const isActive = (el) => {
      return activeElement.value === el ? 'active' : ''
    }
    const addChar = (char) => {
      if (operation.value === '+') {
        activeElement.value === 'x' ?
          xSize.value = +xSize.value + char :
          ySize.value = +ySize.value + char
      } else {
        activeElement.value === 'x' ?
          xSize.value = +xSize.value >= +char ? +xSize.value - char : +xSize.value :
          ySize.value = +ySize.value >= +char ? +ySize.value - char : +ySize.value
      }
    }
    const setSize = computed(() => {
      return {
        width: xSize.value + 'px',
        height: ySize.value + 'px'
      }
    })
    return {
      xSize, ySize, activeElement, addChar, isActive, operation, setSize
    }
  },
})
app.mount("#demo");
.keyboard {
  display: flex;
}
.key {
  margin: 3px;
  width: 30px;
  height: 30px;
  border: 2px black ridge;
}
.test-box {
  border: 2px black ridge;
  background: red;
  margin: 15px;
}
.active {
  background: red;
  color: white;
}
button {
  cursor: pointer;
}
<script src = "https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id = "demo">
  <div>
    <span>xSize </span>
    <input v-model = "xSize" :class = "isActive('x')" @focus = "activeElement = 'x'">
  </div>
  <div>
    <span>ySize </span>
    <input v-model = "ySize" :class = "isActive('y')" @focus = "activeElement = 'y'">
  </div>
  <div class = "keyboard">
    <button @click = "operation = operation === '+' ? '-' : '+'" class = "key">{{ operation }}</button>
    <button v-for = "i in 10" class = "key" :key = "i" @click = "addChar(i)">{{ i }}</button>
  </div>
  <div class = "test-box" :style = "setSize"></div>
</div>

Спасибо за ответ. Честно говоря, мне бы хотелось избежать этого решения, поскольку в реальном проекте оно привело бы к очень большой конструкции «переключателя».

Ruslan54 05.08.2024 05:36
Ответ принят как подходящий

Потому что вы изменили только значение элемента, а не реагирующие данные в данных.

Вы можете изменить код таким образом.

<template>
    <p>xSize</p>
    <input v-model = "xSize" data-name = "xSize">
    <p>ySize</p>
    <input v-model = "ySize" data-name = "ySize">
    <div class = "keyboard">
        <button v-for = "i in [1,2,3,4,5,6,7,8,9,0]" class = "key" :key = "i" @click = "addChar(i)">{{i}}</button>
    </div>
    <p>xSize = {{xSize}}</p>
    <p>ySize = {{ySize}}</p>
    <div class = "test-box" v-bind:style = "{width: this.xSize + 'px', height: this.ySize + 'px'}"></div>


</template>

<script>
export default {
  data: function () {
    return {
      xSize: 50,
      ySize: 50,
      activeElement: null
    }
  },
  props: {

  },
  created() {
    document.addEventListener('focusin', this.focusChanged)
  },
  beforeUnmount() {
    document.removeEventListener('focusin', this.focusChanged)
  },
  methods: {
    focusChanged: function (event) {
      const el = event.target
      if (el.type === "text") {
        if (this.activeElement !== el && this.activeElement !== null) {
          this.activeElement.style.background = "white";
        }

        this.activeElement = el
        this.activeElement.style.background = "red";
      }
    },
    addChar: function (char) {
      if (this.activeElement !== null) {
        const fieldName = this.activeElement.getAttribute("data-name");
        this[fieldName] += char
      }
    }

  }
}
</script>

<style scoped>
    .keyboard {
      display: flex;
    }
    .key {
      margin: 3px;
      width: 30px;
      height: 30px;
      border: 2px black ridge;
    }

    .test-box {
      border: 2px black ridge;
      background: red;
      margin: 15px;
    }
</style>

Да, ваше решение мне помогло. Большое спасибо за помощь!

Ruslan54 05.08.2024 05:46

Другие вопросы по теме