← Назад к вопросам

Как на Web работает взаимодействие со страницей?

2.3 Middle🔥 151 комментариев
#Soft Skills и рабочие процессы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Взаимодействие пользователя со веб-страницей

Взаимодействие на веб — это сложный процесс, который включает события браузера, обработчики, DOM манипуляции и асинхронные операции. Понимание этого процесса критично для создания отзывчивых приложений.

Основные этапы взаимодействия

1. События браузера Действия пользователя (клик, ввод, скролл) генерируют события.

2. Event Propagation События распространяются по DOM дереву (capturing, bubbling).

3. Event Handlers Обработчики событий реагируют на события и выполняют логику.

4. DOM Updates После обработки события обновляется DOM и страница перерисовывается.

5. Reflow и Repaint Браузер пересчитывает разметку и перерисовывает элементы.

6. Event Loop JavaScript Event Loop управляет очередью задач и обработкой событий.

Примеры кода

// События мыши
document.addEventListener('click', (e) => {
  console.log('Клик на:', e.target);
});

document.addEventListener('mousemove', (e) => {
  console.log('Движение мыши:', e.clientX, e.clientY);
});

// События клавиатуры
document.addEventListener('keydown', (e) => {
  console.log('Клавиша нажата:', e.key);
});

// События input
const input = document.querySelector('input');
input.addEventListener('input', (e) => {
  console.log('Значение изменено:', e.target.value);
});

input.addEventListener('change', (e) => {
  console.log('Input изменился окончательно:', e.target.value);
});

input.addEventListener('focus', (e) => {
  console.log('Input получил фокус');
});

input.addEventListener('blur', (e) => {
  console.log('Input потерял фокус');
});

// События скролла
window.addEventListener('scroll', (e) => {
  console.log('Скролл позиция:', window.scrollY);
});

// События изменения размера
window.addEventListener('resize', (e) => {
  console.log('Окно изменило размер:', window.innerWidth, window.innerHeight);
});

Event Propagation

const parent = document.getElementById('parent');
const child = document.getElementById('child');

// Capturing phase (спускается вниз)
parent.addEventListener('click', (e) => {
  console.log('Parent - capturing phase');
}, true);

// Bubbling phase (поднимается вверх)
parent.addEventListener('click', (e) => {
  console.log('Parent - bubbling phase');
});

child.addEventListener('click', (e) => {
  console.log('Child clicked');
  
  // Остановка распространения события
  e.stopPropagation();
  
  // Остановка всех обработчиков
  e.stopImmediatePropagation();
  
  // Отмена действия по умолчанию
  e.preventDefault();
});

Event Delegation

const list = document.getElementById('list');

list.addEventListener('click', (e) => {
  const li = e.target.closest('li');
  if (li) {
    console.log('Нажато на:', li.textContent);
    li.classList.add('active');
  }
});

DOM Updates

function handleButtonClick(e) {
  const button = e.target;
  
  button.textContent = 'Загрузка...';
  button.disabled = true;
  button.classList.add('loading');
  
  fetch('/api/data')
    .then(res => res.json())
    .then(data => {
      const output = document.getElementById('output');
      output.innerHTML = '';
      
      data.forEach(item => {
        const div = document.createElement('div');
        div.textContent = item.name;
        output.appendChild(div);
      });
      
      button.textContent = 'Готово';
      button.disabled = false;
      button.classList.remove('loading');
    })
    .catch(err => {
      console.error('Ошибка:', err);
      button.textContent = 'Ошибка';
    });
}

Event Loop

console.log('Начало');

setTimeout(() => {
  console.log('setTimeout 0ms');
}, 0);

Promise.resolve()
  .then(() => {
    console.log('Promise then');
  });

document.addEventListener('click', () => {
  console.log('Click event');
  
  Promise.resolve()
    .then(() => {
      console.log('Promise in click handler');
    });
});

console.log('Конец');

// Порядок вывода:
// 1. Начало
// 2. Конец
// 3. Promise then
// 4. При клике: Click event
// 5. При клике: Promise in click handler
// 6. setTimeout 0ms

RequestAnimationFrame

let frameCount = 0;

function animate(timestamp) {
  frameCount++;
  
  const element = document.getElementById('animate');
  element.style.left = (frameCount * 2) + 'px';
  
  if (frameCount < 100) {
    requestAnimationFrame(animate);
  }
}

document.addEventListener('click', () => {
  frameCount = 0;
  requestAnimationFrame(animate);
});

Оптимизация производительности

function debounce(func, delay) {
  let timeoutId;
  return function(...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func(...args), delay);
  };
}

function throttle(func, delay) {
  let lastCall = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastCall >= delay) {
      lastCall = now;
      func(...args);
    }
  };
}

// Поиск с debounce
const searchInput = document.getElementById('search');
const handleSearch = debounce((e) => {
  console.log('Поиск:', e.target.value);
  fetch(`/api/search?q=${e.target.value}`);
}, 500);

searchInput.addEventListener('input', handleSearch);

// Скролл с throttle
const handleScroll = throttle(() => {
  console.log('Скролл позиция:', window.scrollY);
  
  if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
    console.log('Конец страницы, загружаем еще');
  }
}, 300);

window.addEventListener('scroll', handleScroll);

Жизненный цикл события

User Action -> Event Created -> Capturing Phase -> Target Phase -> Bubbling Phase -> Event Handlers Execute -> DOM Updates -> Reflow -> Repaint -> Event Complete

Лучшие практики

1. Используй Event Delegation для массивов элементов 2. Используй debounce/throttle для частых событий (скролл, resize) 3. Удаляй обработчики при удалении элементов из DOM 4. Используй passive обработчики для touch и wheel событий 5. Кэшируй DOM элементы вместо повторного поиска

Заключение

Взаимодействие на веб — это многоуровневый процесс, включающий события браузера, распространение событий, обновление DOM и переренднеринг. Понимание Event Loop и оптимизация обработчиков критичны для создания быстрых и отзывчивых приложений.