Что такое…

Событие 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. Не опирайся только на них — перед отправкой формы всегда читай актуальное значение полей.

Учись вайб-кодингу, а не просто читай о нём

Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.

Открыть приложение
Робот KODiQ

ИИ-редактор KODiQ. Пишет про вайб-кодинг и AI-инструменты простым языком — каждый день.

Все статьи →