详细讲解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 元素尺寸变化的"终极解决方案",性能高、用法简单、现代浏览器全支持,是响应式开发的利器。


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


相关推荐
千叶寻-2 小时前
package.json详解
前端·vue.js·react.js·webpack·前端框架·node.js·json
小*-^-*九2 小时前
Electron vue项目 打包 exe文件2
javascript·vue.js·electron
zhengjianyang&1232 小时前
美团滑块-[behavior] 加密分析
javascript·经验分享·爬虫·算法·node.js
zz-zjx2 小时前
Web接入层的“铁三角”---防盗链、反向代理,负载均衡(nginx)
前端·nginx·负载均衡
C+ 安口木2 小时前
CSS通用优惠券样式
前端·css
小趴菜82273 小时前
安卓人机验证View
android·java·前端
weixin_439647793 小时前
JavaScript性能优化实战:从指标到落地的全链路方案
开发语言·javascript·性能优化
闲人编程3 小时前
2025年,如何选择Python Web框架:Django, Flask还是FastAPI?
前端·后端·python·django·flask·fastapi·web
光影少年3 小时前
react打包优化和配置优化都有哪些?
前端·react.js·掘金·金石计划