Найти в Дзене
Concepta junior

Как заставить веб-страницы реагировать: JavaScript события для начинающих

"Ты властен над своим кодом, но не над действиями пользователя. Когда поймёшь это, ты станешь настоящим программистом." Привет! Представь, что ты создал классную веб-страницу с кнопками, полями для ввода текста и другими элементами. Но как сделать так, чтобы что-то происходило, когда пользователь нажимает на кнопку или вводит текст? Здесь на помощь приходят события JavaScript! События - это сигналы, которые браузер посылает, когда что-то происходит на странице. Например: Без обработки событий веб-страницы были бы просто как картинки в книге - красивые, но не интерактивные. Чтобы реагировать на события, мы создаём специальные функции, которые называются обработчиками событий. Они "ловят" события и говорят браузеру, что делать, когда событие происходит. Давай разберём 3 способа создания обработчиков событий: Самый простой способ - добавить атрибут в HTML-тег. Атрибуты начинаются с "on", например onclick, onmouseover: html<button onclick="alert('Привет! Ты нажал на кнопку!')">Нажми меня</
Оглавление
"Ты властен над своим кодом, но не над действиями пользователя. Когда поймёшь это, ты станешь настоящим программистом."

Что такое события и зачем они нужны?

Привет! Представь, что ты создал классную веб-страницу с кнопками, полями для ввода текста и другими элементами. Но как сделать так, чтобы что-то происходило, когда пользователь нажимает на кнопку или вводит текст? Здесь на помощь приходят события JavaScript!

События - это сигналы, которые браузер посылает, когда что-то происходит на странице. Например:

  • Пользователь кликает мышкой
  • Нажимает клавишу на клавиатуре
  • Прокручивает страницу
  • Заполняет форму

Без обработки событий веб-страницы были бы просто как картинки в книге - красивые, но не интерактивные.

Обработчики событий - как поймать событие

Чтобы реагировать на события, мы создаём специальные функции, которые называются обработчиками событий. Они "ловят" события и говорят браузеру, что делать, когда событие происходит.

Давай разберём 3 способа создания обработчиков событий:

Способ 1: Прямо в HTML-коде

Самый простой способ - добавить атрибут в HTML-тег. Атрибуты начинаются с "on", например onclick, onmouseover:

html<button onclick="alert('Привет! Ты нажал на кнопку!')">Нажми меня</button>

Или можно вызвать функцию, которую определили в JavaScript:

html<button onclick="sayHello()">Поздороваться</button>

<script>
function sayHello() {
alert('Привет, мой юный программист!');
}
</script>

Способ 2: Через свойства DOM-элемента

Элементы на странице можно найти с помощью JavaScript и назначить им обработчики:

javascript// Находим кнопку
let button = document.querySelector('button');

// Назначаем обработчик клика
button.onclick = function() {
alert('Кнопка нажата!');
};

// Можно и так:
function showMessage() {
alert('Привет из функции!');
}

button.onclick = showMessage;
// Обрати внимание: без скобок!

Если нужно удалить обработчик:

javascriptbutton.onclick = null; // Обработчик удалён

Способ 3: Метод addEventListener (самый крутой!)

Первые два способа имеют ограничение - с их помощью можно назначить только один обработчик на одно событие. Метод addEventListener позволяет добавлять сколько угодно обработчиков:

javascriptlet button = document.querySelector('button');

// Добавляем первый обработчик
button.addEventListener('click', function() {
console.log('Первый обработчик: Привет!');
});

// Добавляем ещё один обработчик на то же событие
button.addEventListener('click', function() {
console.log('Второй обработчик: И от меня привет!');
});

Чтобы удалить обработчик, используем removeEventListener:

javascriptfunction sayHi() {
alert('Привет!');
}

// Добавляем обработчик
button.addEventListener('click', sayHi);

// Позже, когда нам он больше не нужен:
button.removeEventListener('click', sayHi);

Важно! Нельзя удалить обработчик, если мы не сохранили функцию в переменную:

javascript// ЭТОТ ОБРАБОТЧИК НЕЛЬЗЯ БУДЕТ УДАЛИТЬ:
button.addEventListener('click', function() {
alert('Я навсегда!');
});

// А ЭТОТ МОЖНО:
let myHandler = function() {
alert('Меня можно удалить');
};
button.addEventListener('click', myHandler);

Какие бывают события?

События мыши

  • click - клик (нажатие и отпускание кнопки мыши)
  • mousedown - нажатие кнопки мыши
  • mouseup - отпускание кнопки мыши
  • mousemove - движение мыши
  • mouseover - курсор наводится на элемент
  • mouseout - курсор уходит с элемента

События клавиатуры

  • keydown - нажатие клавиши
  • keyup - отпускание клавиши
  • keypress - нажатие клавиши, которая даёт символ

События форм

  • submit - отправка формы
  • focus - элемент получает фокус
  • blur - элемент теряет фокус
  • change - изменение значения поля формы

События документа

  • DOMContentLoaded - HTML загружен и преобразован в DOM-дерево
  • load - страница полностью загружена
  • scroll - прокрутка страницы

Объект события - откуда берётся информация

Когда происходит событие, браузер создаёт специальный объект события и передаёт его в обработчик. Этот объект содержит полезную информацию о событии:

javascriptbutton.addEventListener('click', function(event) {
// event - это объект события
console.log('Координаты клика:', event.clientX, event.clientY);
console.log('Нажатая кнопка мыши:', event.which);
console.log('Элемент, на котором произошёл клик:', event.target);
});

Всплытие событий: как события путешествуют

Представь, что у тебя есть такая структура HTML:

html<div id="outer">
<div id="inner">
<button id="button">Нажми меня</button>
</div>
</div>

Когда ты кликаешь на кнопку, событие click сначала происходит на самой кнопке, затем на её родителе (inner), потом на родителе родителя (outer) и так далее до самого верхнего элемента. Это называется всплытием событий.

Давай посмотрим, как это работает:

javascriptlet outer = document.getElementById('outer');
let inner = document.getElementById('inner');
let button = document.getElementById('button');

outer.addEventListener('click', function() {
console.log('Клик на внешнем div');
});

inner.addEventListener('click', function() {
console.log('Клик на внутреннем div');
});

button.addEventListener('click', function() {
console.log('Клик на кнопке');
});

Если ты кликнешь на кнопку, то увидишь в консоли:

  1. "Клик на кнопке"
  2. "Клик на внутреннем div"
  3. "Клик на внешнем div"

Это и есть всплытие событий!

Остановка всплытия

Иногда нужно остановить всплытие, чтобы событие не пошло дальше. Для этого используется метод stopPropagation():

javascriptbutton.addEventListener('click', function(event) {
console.log('Клик на кнопке');
event.stopPropagation();
// Событие дальше не пойдёт!
});

Отмена действий по умолчанию

Некоторые элементы имеют встроенные действия: ссылки открывают новую страницу, формы отправляются на сервер и т.д. Иногда нам нужно отменить эти действия и сделать что-то своё. Для этого используется метод preventDefault():

javascript// Простая ссылка
let link = document.querySelector('a');

link.addEventListener('click', function(event) {
event.preventDefault();
// Отменяем переход по ссылке
console.log('Клик по ссылке, но мы остаёмся на странице!');
});

// Отмена отправки формы
let form = document.querySelector('form');

form.addEventListener('submit', function(event) {
event.preventDefault();
// Отменяем отправку формы
console.log('Форма не отправлена!');
});

Практические примеры

Пример 1: Простой счётчик кликов

html<button id="counter">Кликни меня</button>
<p>Количество кликов: <span id="count">0</span></p>

<script>
let button = document.getElementById('counter');
let countDisplay = document.getElementById('count');
let clickCount = 0;

button.addEventListener('click', function() {
clickCount = clickCount + 1;
countDisplay.textContent = clickCount;
});
</script>

Пример 2: Изменение цвета элемента при наведении

html<style>
#colorBox {
width: 200px;
height: 200px;
background-color: blue;
transition: background-color 0.3s;
}
</style>

<div id="colorBox"></div>

<script>
let box = document.getElementById('colorBox');

box.addEventListener('mouseover', function() {
box.style.backgroundColor = 'red';
});

box.addEventListener('mouseout', function() {
box.style.backgroundColor = 'blue';
});
</script>

Пример 3: Простая рисовалка

Этот пример позволяет рисовать точки на странице при клике мышкой:

html<style>
body {
height: 400px;
background: #f0f0f0;
}
.dot {
height: 10px;
width: 10px;
border-radius: 5px;
background: red;
position: absolute;
}
</style>

<script>
document.addEventListener('click', function(event) {
// Создаём новую точку
let dot = document.createElement('div');
dot.className = 'dot';

// Позиционируем точку под курсором
// Вычитаем половину размера точки, чтобы центрировать её
dot.style.left = (event.pageX - 5) + 'px';
dot.style.top = (event.pageY - 5) + 'px';

// Добавляем точку на страницу
document.body.appendChild(dot);
});
</script>

Пример 4: След за курсором мыши

Этот пример создаёт эффект "следа" за курсором:

html<style>
.trail {
position: absolute;
height: 10px;
width: 10px;
border-radius: 5px;
background: purple;
opacity: 0.7;
}
body {
height: 400px;
background: #f0f0f0;
}
</style>

<script>
// Создаём массив элементов следа
let dots = [];
const TRAIL_LENGTH = 10;

// Создаём элементы следа заранее
for (let i = 0; i < TRAIL_LENGTH; i++) {
let dot = document.createElement('div');
dot.className = 'trail';
document.body.appendChild(dot);
dots.push(dot);
}

// Отслеживаем положение курсора
let currentIndex = 0;

document.addEventListener('mousemove', function(event) {
// Перемещаем текущую точку под курсор
dots[currentIndex].style.left = (event.pageX - 5) + 'px';
dots[currentIndex].style.top = (event.pageY - 5) + 'px';

// Переходим к следующей точке в массиве
currentIndex = (currentIndex + 1) % TRAIL_LENGTH;
});
</script>

Делегирование событий

Представь, что у тебя есть список из 100 кнопок и ты хочешь обработать клик на каждой. Было бы неэффективно назначать 100 обработчиков кликов. Вместо этого можно использовать один обработчик на родительском элементе, а затем проверять, на каком именно элементе произошёл клик. Это называется делегированием событий:

html<div id="buttons-container">
<button data-action="like">Лайк</button>
<button data-action="share">Поделиться</button>
<button data-action="comment">Комментировать</button>
</div>

<script>
let container = document.getElementById('buttons-container');

container.addEventListener('click', function(event) {
// Проверяем, был ли клик по кнопке
if (event.target.tagName === 'BUTTON') {
// Получаем действие из атрибута data-action
let action = event.target.dataset.action;

// Выполняем нужное действие
switch(action) {
case 'like':
console.log('Поставлен лайк!');
break;
case 'share':
console.log('Пост отправлен друзьям!');
break;
case 'comment':
console.log('Открываем окно комментария!');
break;
}
}
});
</script>

Таймеры: выполнение кода через время

В JavaScript есть две функции для запуска кода через определённое время:

setTimeout - выполнить один раз

javascript// Меняем цвет фона через 2 секунды
document.body.style.background = "blue";

setTimeout(function() {
document.body.style.background = "green";
}, 2000);
// 2000 миллисекунд = 2 секунды

Можно отменить запланированное выполнение:

javascriptlet timerId = setTimeout(function() {
alert("Бум!");
}, 1000);

// Если передумали:
clearTimeout(timerId);

setInterval - выполнять регулярно

javascript// Создаём мигающий эффект
let isRed = false;
let blinkerId = setInterval(function() {
if (isRed) {
document.body.style.background = "";
} else {
document.body.style.background = "red";
}
isRed = !isRed;
}, 500);
// Каждые полсекунды

// Останавливаем мигание через 5 секунд
setTimeout(function() {
clearInterval(blinkerId);
document.body.style.background = "";
}, 5000);

Ограничение частоты событий (debouncing)

Некоторые события (например, mousemove или scroll) могут происходить ОЧЕНЬ часто. Если обработчик выполняет сложные операции, страница может тормозить. Для решения этой проблемы используется техника "debouncing":

javascript// Пример: показываем координаты мыши, но не чаще чем раз в 250 мс
function showCoords(event) {
document.body.textContent =
"Мышь на координатах: " + event.pageX + ", " + event.pageY;
}

let timeout;
document.addEventListener("mousemove", function(event) {
// Отменяем предыдущий запланированный вызов
clearTimeout(timeout);

// Планируем новый вызов
timeout = setTimeout(function() {
showCoords(event);
}, 250);
});

Заключение

События JavaScript - это как нервная система для веб-страницы. Они связывают действия пользователя с реакциями страницы, делая её живой и интерактивной.

Теперь ты знаешь:

  • Как обрабатывать события разными способами
  • Какие бывают события и что они означают
  • Как события всплывают по DOM-дереву
  • Как отменять действия по умолчанию
  • Как использовать делегирование событий для оптимизации кода
  • Как использовать таймеры для выполнения кода через время

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

Практические задания для тренировки

Задание 1: Цензура клавиатуры

Создай текстовое поле, которое не позволяет вводить определённые буквы (например, Q, W и X):

html<input type="text" id="censored-input" placeholder="Попробуй ввести Q, W или X">

<script>
let input = document.getElementById('censored-input');

input.addEventListener('keydown', function(event) {
// Получаем символ нажатой клавиши (переводим в верхний регистр для проверки)
let char = String.fromCharCode(event.keyCode).toUpperCase();

// Проверяем, входит ли символ в список запрещённых
if (char === 'Q' || char === 'W' || char === 'X') {
// Если да, отменяем действие по умолчанию (ввод символа)
event.preventDefault();
console.log('Буква ' + char + ' запрещена!');
}
});
</script>

Задание 2: Простые вкладки

Создай простую систему вкладок:

html<style>
.tab-content {
display: none;
padding: 10px;
border: 1px solid #ccc;
}

.active-tab {
display: block;
}

.tab-button {
padding: 5px 10px;
margin-right: 5px;
background: #f0f0f0;
border: 1px solid #ccc;
cursor: pointer;
}

.active-button {
background: #ccc;
}
</style>

<div id="tabs-container">
<div id="tabs-buttons"></div>

<div class="tab-content" data-tab="tab1">
<h3>Вкладка 1</h3>
<p>Содержимое первой вкладки.</p>
</div>

<div class="tab-content" data-tab="tab2">
<h3>Вкладка 2</h3>
<p>Содержимое второй вкладки.</p>
</div>

<div class="tab-content" data-tab="tab3">
<h3>Вкладка 3</h3>
<p>Содержимое третьей вкладки.</p>
</div>
</div>

<script>
// Находим все вкладки
let tabs = document.querySelectorAll('.tab-content');
let buttonsContainer = document.getElementById('tabs-buttons');

// Создаём кнопки для каждой вкладки
tabs.forEach(function(tab) {
let tabName = tab.dataset.tab;
let button = document.createElement('button');
button.className = 'tab-button';
button.textContent = tabName;
button.dataset.tabTarget = tabName;
buttonsContainer.appendChild(button);
});

// Делаем первую вкладку активной по умолчанию
tabs[0].classList.add('active-tab');
document.querySelector('.tab-button').classList.add('active-button');

// Обработчик кликов по кнопкам
buttonsContainer.addEventListener('click', function(event) {
// Проверяем, что клик был по кнопке
if (event.target.classList.contains('tab-button')) {
// Удаляем активный класс у всех вкладок и кнопок
tabs.forEach(function(tab) {
tab.classList.remove('active-tab');
});

let buttons = document.querySelectorAll('.tab-button');
buttons.forEach(function(button) {
button.classList.remove('active-button');
});

// Добавляем активный класс нужной вкладке и кнопке
let targetTabName = event.target.dataset.tabTarget;
document.querySelector(`.tab-content[data-tab="${targetTabName}"]`).classList.add('active-tab');
event.target.classList.add('active-button');
}
});
</script>

Используй эти примеры как начальную точку и экспериментируй с ними, добавляя новые функции и улучшения. Так ты научишься использовать события JavaScript и сможешь создавать интерактивные веб-страницы!