Skip to content

观察者 API

概述

浏览器提供多种观察者 API,用于高效监听 DOM 变化和元素状态。

一、IntersectionObserver (交叉观察)

用途:懒加载、无限滚动、曝光统计

javascript
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // 元素进入视口
      entry.target.src = entry.target.dataset.src;
      observer.unobserve(entry.target);
    }
  });
}, {
  root: null,        // 视口
  rootMargin: '100px', // 提前加载
  threshold: 0.1     // 10% 可见时触发
});

document.querySelectorAll('img[data-src]').forEach(img => {
  observer.observe(img);
});

二、MutationObserver (DOM 变化)

用途:监听 DOM 修改

javascript
const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    console.log(mutation.type); // childList, attributes, characterData
    console.log(mutation.addedNodes);
    console.log(mutation.removedNodes);
  });
});

observer.observe(document.body, {
  childList: true,    // 子节点变化
  attributes: true,   // 属性变化
  characterData: true,// 文本内容变化
  subtree: true,      // 后代节点
  attributeOldValue: true
});

observer.disconnect(); // 停止观察

三、ResizeObserver (尺寸变化)

用途:响应式组件

javascript
const observer = new ResizeObserver((entries) => {
  entries.forEach(entry => {
    const { width, height } = entry.contentRect;
    console.log(`Size: ${width} x ${height}`);
  });
});

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

四、PerformanceObserver (性能)

javascript
const observer = new PerformanceObserver((list) => {
  list.getEntries().forEach(entry => {
    console.log(entry.name, entry.duration);
  });
});

observer.observe({ entryTypes: ['resource', 'paint', 'longtask'] });

面试高频题

Q1: IntersectionObserver vs scroll 事件?

Observer 异步执行、性能更好;scroll 事件同步、可能导致性能问题。

Q2: MutationObserver 的应用场景?

监控第三方脚本注入、实现 undo/redo、虚拟 DOM 替代方案。

Q3: 如何检测元素尺寸变化?

使用 ResizeObserver,比监听 window.resize 更精确。

前端面试知识库