ResizeObserver: наблюдение за изменением размеров элемента

Что такое ResizeObserver и зачем он нужен? 🤔

Представь ситуацию: ты разрабатываешь адаптивный интерфейс, и тебе нужно реагировать на изменение размеров элемента. Раньше для этого использовали window.resize, но он срабатывает только при изменении размеров окна. А если изменился размер конкретного div? Вот тут на сцену выходит ResizeObserver — современный API, который отслеживает изменения размеров любого элемента!

const observer = new ResizeObserver(entries => {
  for (let entry of entries) {
    console.log('Размер изменился!', entry.contentRect);
  }
});

observer.observe(document.querySelector('.resizable-box'));

Как работает ResizeObserver? 🔍

ResizeObserver использует механизм колбэков, которые вызываются при каждом изменении размеров наблюдаемого элемента. Вот ключевые особенности:

  • Эффективность: Срабатывает только при реальных изменениях
  • Гибкость: Можно наблюдать за несколькими элементами одновременно
  • Точность: Предоставляет детальную информацию о новых размерах

💡 Совет: ResizeObserver работает асинхронно — изменения собираются в «пачки» и обрабатываются перед отрисовкой кадра, что улучшает производительность.


Практический пример: адаптивный компонент 🛠️

Допустим, мы создаём компонент, который должен менять стиль при достижении определённой ширины:

const responsiveComponent = document.querySelector('.responsive-component');

const resizeObserver = new ResizeObserver(entries => {
  const [entry] = entries;
  if (entry.contentRect.width < 600) {
    entry.target.classList.add('mobile-layout');
    entry.target.classList.remove('desktop-layout');
  } else {
    entry.target.classList.add('desktop-layout');
    entry.target.classList.remove('mobile-layout');
  }
});

resizeObserver.observe(responsiveComponent);

Детали наблюдения: что содержит entry? 📊

Каждый entry в колбэке содержит полезную информацию:

Свойство Описание
target Наблюдаемый DOM-элемент
contentRect Объект с размерами и позицией
borderBoxSize Размеры с учётом border
contentBoxSize Размеры содержимого

Пример доступа к данным:

new ResizeObserver(entries => {
  entries.forEach(entry => {
    console.log('Ширина:', entry.contentRect.width);
    console.log('Высота:', entry.contentRect.height);
    console.log('Новые размеры:', entry.contentBoxSize[0]);
  });
});

Важные нюансы при работе 🚨

1. Отмена наблюдения:

const observer = new ResizeObserver(callback);
const element = document.getElementById('my-element');

// Начать наблюдение
observer.observe(element);

// Прекратить наблюдение
observer.unobserve(element);

// Отключить все наблюдения
observer.disconnect();

2. Производительность: Не забывай отключать наблюдение за элементами, которые больше не нужны.

3. Совместимость: ResizeObserver поддерживается всеми современными браузерами, но для старых версий может потребоваться полифил.


Реальный кейс: адаптивные диаграммы 📈

Представим, что у нас есть диаграмма, которая должна перерисовываться при изменении размеров контейнера:

class ResponsiveChart {
  constructor(container) {
    this.container = container;
    this.chart = this.initChart();
    this.observer = new ResizeObserver(this.handleResize.bind(this));
    this.observer.observe(container);
  }

  handleResize(entries) {
    const [entry] = entries;
    this.updateChart(entry.contentRect.width, entry.contentRect.height);
  }

  updateChart(width, height) {
    console.log(`Обновляем диаграмму для ${width}x${height}`);
    // Логика перерисовки диаграммы...
  }
}

new ResponsiveChart(document.querySelector('.chart-container'));

Альтернативы и сравнение ⚖️

До ResizeObserver разработчики использовали:

  1. window.resize — реагирует только на окно
  2. MutationObserver — слишком общий, не оптимизирован под размеры
  3. Периодическая проверка — неэффективно и ресурсоёмко

ResizeObserver решает все эти проблемы, предоставляя специализированное и эффективное API.


Итоги и лучшие практики 🏆

  1. Всегда отключай наблюдение за ненужными элементами
  2. Используй contentBoxSize для точных измерений содержимого
  3. Оптимизируй колбэки — избегай тяжёлых вычислений
  4. Комбинируй с другими API (например, IntersectionObserver)
// Оптимизированный пример
const optimizedObserver = new ResizeObserver(entries => {
  requestAnimationFrame(() => {
    entries.forEach(entry => {
      // Лёгкие вычисления здесь
    });
  });
});

Теперь ты вооружён мощным инструментом для создания по-настоящему адаптивных интерфейсов! 🚀

Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео