详细讲解js中的ResizeObserver

一、ResizeObserver 是什么?

ResizeObserver 是一个 JavaScript 内置 API ,用于 异步监听一个或多个 DOM 元素的尺寸变化(content-box 或 border-box) 。当元素的 内容区域(content rect) 发生变化时,它会触发回调函数,而 不需要等待浏览器重绘或滚动事件


二、为什么需要 ResizeObserver?

在 ResizeObserver 出现之前,开发者通常使用以下方式监听元素尺寸变化:

方法 缺点
window.resize 只能监听窗口大小变化,无法监听单个元素
MutationObserver 只能监听 DOM 结构变化,无法监听尺寸变化
定时器(setInterval 性能差,频繁触发,浪费资源
objectiframe hack 复杂、不优雅、兼容性差

ResizeObserver 的优势:

  • 精准监听任意元素 的尺寸变化
  • 高性能,浏览器内部优化,避免重排
  • 异步触发,不会阻塞渲染
  • 支持监听多个元素

三、基本用法

1. 创建观察者

js 复制代码
const observer = new ResizeObserver(entries => {
  for (const entry of entries) {
    console.log('尺寸变化:', entry.target);
    console.log('新尺寸:', entry.contentRect);
  }
});

2. 监听元素

js 复制代码
const box = document.querySelector('.box');
observer.observe(box);

3. 停止监听

js 复制代码
observer.unobserve(box);   // 停止监听某个元素
observer.disconnect();     // 停止监听所有元素

四、回调参数详解:ResizeObserverEntry

每个 entry 是一个 ResizeObserverEntry 对象,包含以下属性:

属性 类型 含义
target Element 被监听的 DOM 元素
contentRect DOMRectReadOnly 内容区域的尺寸(不含 padding/border)
borderBoxSize ResizeObserverSize[] 边框盒子尺寸(含 padding/border)
contentBoxSize ResizeObserverSize[] 内容盒子尺寸(不含 padding/border)
devicePixelContentBoxSize ResizeObserverSize[] 物理像素级别的内容盒子尺寸(用于 Canvas 等高精度场景)

⚠️ 注意:borderBoxSizecontentBoxSize数组,因为未来可能支持多列布局。


五、完整示例:监听一个 div 的尺寸变化

html 复制代码
<div class="box" style="width: 200px; height: 100px; background: lightblue;"></div>
<button onclick="changeSize()">改变尺寸</button>

<script>
  const box = document.querySelector('.box');

  const observer = new ResizeObserver(entries => {
    for (const entry of entries) {
      const { width, height } = entry.contentRect;
      console.log(`新尺寸: ${width}x${height}`);
    }
  });

  observer.observe(box);

  function changeSize() {
    box.style.width = Math.random() * 300 + 'px';
    box.style.height = Math.random() * 200 + 'px';
  }
</script>

六、性能优化与注意事项

✅ 1. 防抖与节流不需要

ResizeObserver 本身已经由浏览器 异步批量处理不需要手动防抖或节流

✅ 2. 避免在回调中修改尺寸

在回调中修改元素尺寸可能导致 无限循环,如下:

js 复制代码
// ❌ 错误示例:无限循环
observer.observe(box);
observer.onResize = () => {
  box.style.width = '300px'; // 又会触发回调
};

✅ 3. 使用 requestAnimationFrame 优化绘制

如果需要在回调中触发重绘(如 Canvas),建议配合 requestAnimationFrame

js 复制代码
let rafId;
observer.observe(canvas);
observer.onResize = () => {
  cancelAnimationFrame(rafId);
  rafId = requestAnimationFrame(() => {
    redrawCanvas();
  });
};

七、兼容性(2025年更新)

浏览器 支持情况
Chrome ✅ 64+(2018年)
Firefox ✅ 69+
Safari ✅ 13.1+
Edge ✅ 79+(Chromium 内核)
IE ❌ 不支持

✅ 现代浏览器已全面支持,可放心使用


八、Polyfill(兼容旧浏览器)

使用 @juggle/resize-observer polyfill:

bash 复制代码
npm install @juggle/resize-observer
js 复制代码
import { ResizeObserver } from '@juggle/resize-observer';

if (!window.ResizeObserver) {
  window.ResizeObserver = ResizeObserver;
}

九、实际应用场景

场景 用法
图表自适应 ECharts、Canvas 图表随容器变化重绘
响应式布局 自定义组件根据尺寸调整内部布局
虚拟滚动 根据容器高度动态计算可视区域
广告容器 监听广告位尺寸变化,触发重新加载
拖拽缩放 监听用户拖拽后容器尺寸变化

十、总结一句话

ResizeObserver 是监听 DOM 元素尺寸变化的"终极解决方案",性能高、用法简单、现代浏览器全支持,是响应式开发的利器。


十一、进阶阅读(官方文档)


相关推荐
谢尔登10 分钟前
10_从 React Hooks 本质看 useState
前端·ubuntu·react.js
辰同学ovo12 分钟前
从全局登录状态管理学习 Redux
前端·javascript·学习·react.js
爱看书的小沐16 分钟前
【小沐杂货铺】基于Three.js绘制三维艺术画廊3DArtGallery (Three.js,WebGL)
javascript·3d·webgl·three.js·babylon.js·三维画廊
陈随易33 分钟前
2年没用Nodejs了,Bun很香
前端·后端·程序员
donecoding1 小时前
Corepack 完全解析:从懵到懂,包管理器自由了
前端·node.js·前端工程化
yqcoder1 小时前
端经典面试题:为什么 0.1 + 0.2 !== 0.3?
前端·css
ZC跨境爬虫1 小时前
跟着 MDN 学 HTML day_12:(HTML网页图片嵌入)
前端·javascript·css·ui·html
光影少年1 小时前
reeact虚拟DOM、Diff算法原理、key的作用与为什么不能用index
前端·react.js·掘金·金石计划
用户059540174461 小时前
大模型记忆存储踩坑实录:LangChain 的 ConversationBufferMemory 让我排查了 6 小时
前端·css
是上好佳佳佳呀1 小时前
【前端(十二)】JavaScript 函数与对象笔记
前端·javascript·笔记