Code Ready | Frontend
Почему change не всегда подходит для отслеживания изменений в input!
При работе с формами часто пытаются отслеживать ввод через событие change:
input.addEventListener('change', event => {
console.log(event.target.value);
});
Но для текстовых полей это не всегда правильный вариант. change срабатывает не при каждом изменении текста, а после того, как пользователь изменил значение и завершил редактирование, например покинул поле.
Если интерфейс должен реагировать непосредственно во время ввода, используется событие input:
input.addEventListener('input', event => {
console.log(event.target.value);
});
Теперь обработчик вызывается при каждом изменении значения:
J
Ja
Jav
Java
При этом input — это не просто реакция на нажатие клавиш. Событие возникает и при других действиях пользователя, например при вставке текста, удалении, вставке через контекстное меню или перемещении текста через drag & drop.
Например, динамический поиск обычно строят так:
search.addEventListener('input', event => {
const query = event.target.value.trim();
filterItems(query);
});
Частая ошибка — использовать keyup как замену input:
input.addEventListener('keyup', handler);
Но эти события решают разные задачи. keyup реагирует только на отпускание клавиши, поэтому он не поймает вставку мышью, автозаполнение браузера и другие изменения значения без клавиатуры.
У события input есть дополнительная информация через InputEvent:
input.addEventListener('input', event => {
console.log(event.inputType);
});
Например, можно определить, было ли действие вставкой текста, удалением символа или вставкой из буфера обмена.
Если обработчик input запускает тяжёлую операцию или запрос к API, обычно используют debounce, чтобы не выполнять действие после каждого символа:
search.addEventListener(
'input',
debounce(event => {
fetchResults(event.target.value);
}, 300)
);
При этом у change остаются свои правильные сценарии. Например, для <select> он хорошо подходит, потому что важен момент выбора нового значения:
select.addEventListener('change', event => {
updateLanguage(event.target.value);
});
Важный нюанс: программное изменение value само по себе не создаёт событие input:
input.value = 'JavaScript';
Браузер отличает изменение через код от реального пользовательского ввода. Если приложению нужно уведомить другие части системы, событие можно вызвать отдельно:
input.value = 'JavaScript';
input.dispatchEvent(
new Event('input', { bubbles: true })
);
Но такое событие будет синтетическим (isTrusted === false), а не настоящим действием пользователя.
В сложных редакторах также учитывают IME-ввод, например при работе с китайской, японской или корейской раскладкой. Во время композиции можно проверить:
input.addEventListener('input', event => {
if (event.isComposing) {
return;
}
processValue(event.target.value);
});
🔥 Главное правило простое: если нужно реагировать на процесс редактирования в реальном времени — используйте input. Если нужно получить факт завершённого изменения значения — подходит change. Если нужно отслеживать только действия клавиатуры — используйте keyup, понимая его ограничения.
📣 Code Ready | #практика
25 · 1.6K ·