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 разработчики использовали:
- window.resize — реагирует только на окно
- MutationObserver — слишком общий, не оптимизирован под размеры
- Периодическая проверка — неэффективно и ресурсоёмко
ResizeObserver решает все эти проблемы, предоставляя специализированное и эффективное API.
Итоги и лучшие практики 🏆
- Всегда отключай наблюдение за ненужными элементами
- Используй
contentBoxSizeдля точных измерений содержимого - Оптимизируй колбэки — избегай тяжёлых вычислений
- Комбинируй с другими API (например, IntersectionObserver)
// Оптимизированный пример
const optimizedObserver = new ResizeObserver(entries => {
requestAnimationFrame(() => {
entries.forEach(entry => {
// Лёгкие вычисления здесь
});
});
});
Теперь ты вооружён мощным инструментом для создания по-настоящему адаптивных интерфейсов! 🚀