Значение Vue.JS, привязанное к входу, имеющему фокус

Есть ли способ изменить значение в модели, когда вход получает/теряет фокус?

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

Вот что у меня так далеко:

<input type="search" v-model="query">
<div class="results-as-you-type" v-if="magic_flag"> ... </div>

А потом,

new Vue({
  el: '#search_wrapper',
  data: {
    query: '',
    magic_flag: false
  }
});

Идея в том, что magic_flag должен стать true когда окно поиска имеет фокус. Я мог бы сделать это вручную (например, с помощью jQuery), но мне нужно чистое решение Vue.JS.

Ответ 1

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

<input 
  type="search" 
  v-model="query"
  @focus="magic_flag = true"
  @blur="magic_flag = false"
/>
<div class="results-as-you-type" v-if="magic_flag"> ... </div>

Ответ 2

Вы также можете активировать поиск, когда пользователь переводит мышью поверх ввода - @mouseover =...

Другим подходом к такого рода функциям является то, что вход фильтра всегда активен, даже когда мышь находится в списке результатов. Ввод любых букв изменяет вход фильтра без изменения фокусировки. Многие реализации фактически показывают поле ввода фильтра только после ввода буквы или цифры.

Посмотрите на @event.capture.

Ответ 3

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

Я покажу быстрый образец:

<input
    v-model="user.foo"
    type="text"
    name="foo"
    @focus="currentlyActiveField = 'foo'"
>

<input
    ref="bar"
    v-model="user.bar"
    type="text"
    name="bar"
    @focus="currentlyActiveField = 'bar'"
>

...

data() {
    return {
        currentlyActiveField: '',
        user: {
            foo: '',
            bar: '',
        },
    };
},

watch: {
    user: {
        deep: true,
        handler(user) {
            if ((this.currentlyActiveField === 'foo') && (user.foo.length === 4)) {
                // the field is focused and some condition is met
                this.$refs.bar.focus();
            }
        },
    },
},

В моем примере здесь, если текущее активное поле имеет значение foo а значение имеет длину 4 символа, тогда следующая bar поля будет автоматически сфокусирована. Этот тип логики полезен при работе с формами, которые имеют такие вещи, как номер кредитной карты, срок действия кредитной карты и ввод кода безопасности кредитной карты. UX может быть улучшен таким образом.

Я надеюсь, что это может стимулировать ваше творчество. Наблюдатели удобны тем, что позволяют вам прислушиваться к изменениям в вашей модели данных и действовать в соответствии с вашими потребностями в момент запуска наблюдателя.

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

Наблюдатель, который я показал, немного более сложен в том смысле, что это "глубокий" наблюдатель, что означает, что он способен наблюдать за объектами и массивами. Без deep: true наблюдатель будет срабатывать только в случае переназначения user, но мы этого не хотим. Смотрим клавиши foo и bar на user.

За кулисами deep: true добавляет наблюдателей ко всем ключам этого this.user. В противном случае Vue не несет затрат на это.

Простой наблюдатель будет выглядеть так:

watch: {
    user() {
        console.log('user changed');
    },
},

Примечание. Если вы обнаружите, что там, где у меня есть handler(user) {, у вас может быть handler(oldValue, newValue) { но вы заметите, что оба показывают одно и то же значение, потому что оба являются ссылкой на один и тот же объект user. Узнайте больше здесь: https://github.com/vuejs/vue/issues/2164