IntersectionObserver, ResizeObserver, MutationObserver

↑ 7.4 Browser API · → Следующая

Желательно~3 мин чтенияУровень: senior

Зачем это на собесе

Три 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() при размонтировании, иначе утечка.

Вопросы с ответами