观察者 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 更精确。