Почему input.value не меняется второй раз

276
24 января 2018, 17:04

Делаю свой input, ввожу в него данные и он сразу их заменяет на "11.11", так у меня и должно быть. Но если после этой замены я продолжаю вводить данные, он перестаёт их заменять, этого я не понимаю.

У меня стоит v-bind:value="val" и по идее если я перезаписываю this.val он должен это отображать в инпуте. Сам val меняется, я его выводу, но не в инпуте.

Vue.component('currency-input', { 
  template: `<span> 
      <input 
        v-bind:value="val" 
        v-on:input="updateValue($event.target.value)"> val: {{val}} 
    </span>`, 
  data: function() { 
    return { 
      val: "" 
    }; 
  }, 
  methods: { 
    updateValue: function(value) { 
      this.val = "11.11"; 
    } 
  } 
}); 
 
// создание корневого экземпляра 
var app = new Vue({ 
  el: '#app', 
  template: `<div> 
                    <currency-input></currency-input> 
                    </div>`, 
 
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script> 
<div id="app"> 
 
</div>

Answer 1

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

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

Привязку данных следует применять только в тех случаях когда есть лишь один источник изменений в один момент времени, а не когда два источника данных (вы и пользователь) "дерутся" за одно и то же свойство.

v-model же работает потому что в свойство val записываются сначала данные от пользователя, потом ваши. Но это не решение: использовав v-model вы больше не сможете гарантировать что в свойстве val находится именно то что вам нужно.

Правильно в таком случае работать с элементом напрямую.

PS если вы пытаетесь таким хитрым образом сделать фильтрацию вводимых символов - лучше блокируйте нежелательные символы через preventDefault() а не через присвоение value. Присвоение value сбрасывает текущее положение текстового курсора.

Answer 2

Есть два варианта:

A. Использовать v-model для двустороннего связывания:

<input v-model="val" v-on:input="updateValue($event.target.value)">

B. Создать ссылку на input:

<input ref="input" v-bind:value="val" v-on:input="updateValue($event.target.value)">

и в методе updateValue явно обновлять значение поля ввода:

this.$refs.input.value = this.val;

Документация

READ ALSO
Валидация и приведение к одному формату номера телефона

Валидация и приведение к одному формату номера телефона

Нужно валидировать номера телефонов и приводить их к одному форматуесли введен номер через (8 999

287
Как скопировать и отправить на почту текст со страницы сайта

Как скопировать и отправить на почту текст со страницы сайта

Есть сайт с определенным текстом, ниже текста кнопка отправитьСам текст динамичный, т

332
Багается Bootstrap carousel при вставке ее в Tabs

Багается Bootstrap carousel при вставке ее в Tabs

При попытке вставить слайдер в tab's (на каждой вкладке должно быть по 1 слайдеру) слайдеры начинают багаться при переключении вкладокПри переходе...

334