Событие input или change — и почему поиск срабатывает только после клика мимо

Ты делаешь поиск «на лету». Человек печатает «кроссовки» — а результаты не меняются. Он печатает дальше. Ничего. Потом кликает куда-то мимо поля — и результаты наконец появляются.
Код при этом рабочий. Просто ты повесил обработчик на событие change. А оно срабатывает не тогда, когда меняется текст, а когда человек закончил его менять. Для поиска нужно было input.
Разбираемся, чем они отличаются и когда какое брать.
Коротко: в чём разница
input— срабатывает на каждое изменение значения. Каждая буква, каждое удаление, каждая вставка из буфера.change— срабатывает, когда изменение зафиксировано. Для текстового поля это обычно момент, когда оно теряет фокус. В большинстве браузеров ещё и по Enter.
Аналогия: input — это друг, который читает через плечо, пока ты пишешь. change — тот, кто ждёт, пока ты отдашь ему готовый листок.
Оба события — часть DOM, обычные браузерные события. Подписываешься одинаково:
field.addEventListener("input", (e) => search(e.target.value))
field.addEventListener("change", (e) => save(e.target.value))
Сравнение по полям формы
Поведение change зависит от типа поля. Это главный источник путаницы:
- Текст, textarea.
input— на каждую букву.change— когда ушёл из поля (или нажал Enter). Если текст вернули к исходному,changeне сработает вовсе. - Чекбокс, радиокнопка. Оба срабатывают сразу по клику. Тут разницы почти нет — бери
change, так принято. И не бериclick: галочку ставят ещё пробелом с клавиатуры и кликом по подписи.changeпоймает все три способа. - Выпадающий список
select. Оба срабатывают сразу после выбора. - Слайдер
type="range".input— непрерывно, пока тащишь ползунок.change— один раз, когда отпустил. Вот тут разница огромная. - Цвет, дата, файл.
change— когда выбор подтверждён в окне выбора. Дляtype="file"слушай именноchange.
Пример со слайдером. Громкость в плеере: подписка на input — звук меняется, пока двигаешь ползунок. Подписка на change — звук скачком прыгает в конце. А вот сохранять громкость на сервер лучше по change. Иначе за одно движение улетит сто запросов.
Подвох в React
В React есть onChange. Логично ожидать, что это change. Но нет.
onChange в React срабатывает на каждое нажатие клавиши — то есть ведёт себя как браузерный input. Это прямо сказано в документации React. Сделано, чтобы управляемые поля обновляли состояние сразу.
Отсюда две ловушки:
- Переходишь с React на чистый JavaScript, пишешь
addEventListener("change", ...)и ждёшь того же поведения. А получаешь «поиск после клика мимо». - Переходишь наоборот — и удивляешься, почему
onChangeдёргает сохранение на каждую букву.
Если в React тебе нужно именно «человек закончил ввод», используй onBlur. Подробнее про обработчики, которые передаются в onChange, — в статье что такое колбэк. А про то, как устроен сам React, — отдельно.
Во Vue похоже: v-model слушает input, а v-model.lazy — change.
Ещё два сюрприза
Программное изменение молчит. Если код сам написал field.value = "привет", ни input, ни change не сработают. События — только про действия человека. Нужно уведомить остальной код — вызови field.dispatchEvent(new Event("input", { bubbles: true })).
Китайский и японский ввод. Пока человек набирает иероглиф через подсказки клавиатуры, input срабатывает на промежуточные состояния. Поиск полетит по половинке слова. Проверяй e.isComposing и пропускай такие события.
Кому что подойдёт — вердикт
- Поиск, фильтр, живой счётчик символов, превью —
input. Человек должен видеть результат сразу. Чтобы не слать запрос на каждую букву, добавь задержку 300 мс перед поиском. - Сохранение на сервер, валидация «по выходу из поля», аналитика —
change. Одно событие на одно законченное действие. - Чекбоксы, радиокнопки, select, файлы —
change. Он срабатывает сразу, а код читается привычно. - Слайдер — оба:
inputдля живого отклика,changeдля сохранения.
Не уверен? Бери input. Лишняя реакция раздражает меньше, чем отсутствующая.
Сработает ли change, если нажать кнопку «Сохранить»?
Да. Клик по кнопке уводит фокус из поля, и change успевает сработать раньше, чем click. Но на телефоне иногда форма отправляется по кнопке на клавиатуре — тогда надёжнее читать значение прямо в обработчике отправки.
Что делать с автозаполнением браузера?
Браузер при автозаполнении генерирует события, но набор и порядок отличаются между Chrome, Safari и Firefox. Не опирайся только на них — перед отправкой формы всегда читай актуальное значение полей.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





