IntersectionObserver, ResizeObserver, MutationObserver
↑ 7.4 Browser API · → Следующая
Зачем это на собесе
Три observer-а заменяют scroll-слушатели и опрос DOM. Спрашивают, когда какой применять.
IntersectionObserver
Сообщает, когда элемент входит в область видимости (viewport или контейнер).
const io = new IntersectionObserver(
entries => entries.forEach(e => {
if (e.isIntersecting) { loadImage(e.target as HTMLImageElement); io.unobserve(e.target) }
}),
{ root: null, rootMargin: '200px', threshold: 0.1 },
)
io.observe(el)Применение: lazy loading, бесконечная прокрутка (sentinel-элемент), аналитика видимости, подсветка пункта меню, ленивая гидрация.
ResizeObserver
Реагирует на изменение размера элемента (а не окна).
const ro = new ResizeObserver(([entry]) => {
const { width } = entry.contentRect
compact.value = width < 480
})
ro.observe(container)Применение: адаптивные компоненты (container-based), графики, виртуальные списки, авторазмер textarea.
Нюанс: изменение размера внутри колбэка может вызвать цикл (ResizeObserver loop), используйте requestAnimationFrame.
MutationObserver
Следит за изменениями DOM (дети, атрибуты, текст).
const mo = new MutationObserver(list => list.forEach(m => console.log(m.type)))
mo.observe(el, { childList: true, attributes: true, subtree: true })Применение: интеграция со сторонним кодом, расширения, определение появления элемента. Во Vue редко нужен: реактивность заменяет.
Composable
export function useElementSize(el: Ref<HTMLElement | null>) {
const size = reactive({ width: 0, height: 0 })
let ro: ResizeObserver
onMounted(() => {
ro = new ResizeObserver(([e]) => { size.width = e.contentRect.width; size.height = e.contentRect.height })
if (el.value) ro.observe(el.value)
})
onBeforeUnmount(() => ro?.disconnect())
return size
}Готовые: VueUse (useIntersectionObserver, useElementSize, useMutationObserver).
Всегда отключайте
disconnect() или unobserve() при размонтировании, иначе утечка.
Вопросы с ответами
Почему IntersectionObserver лучше scroll-события?
Работает асинхронно вне основного потока обработки прокрутки, не вызывает layout при каждом событии, браузер оптимизирует проверки.
Чем ResizeObserver лучше window.resize?
Следит за размером конкретного элемента, а не окна: подходит для компонентов, которые меняют размер от макета.