详细讲解js中的ResizeObserver

一、ResizeObserver 是什么?

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


二、为什么需要 ResizeObserver?

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

方法 缺点
window.resize 只能监听窗口大小变化,无法监听单个元素
MutationObserver 只能监听 DOM 结构变化,无法监听尺寸变化
定时器(setInterval) 性能差,频繁触发,浪费资源
object 或 iframe 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 等高精度场景)

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


五、完整示例:监听一个 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 元素尺寸变化的"终极解决方案",性能高、用法简单、现代浏览器全支持,是响应式开发的利器。


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


相关推荐
hzxpaipai4 分钟前
杭州企业官网怎么建设?从策划到上线的5步建站方法
运维·服务器·前端·网络
怕浪猫9 分钟前
2026年金九银十,我面了22个前端
前端·javascript·面试
IT_陈寒15 分钟前
Vue 这个响应式陷阱,我的头发都掉没了
前端·人工智能·后端
前端的日常21 分钟前
一个人+AI做情侣食谱小程序,30天纯赚
前端·javascript·后端
qq_316837751 小时前
阿里云百炼 fun-asr-realtime uniapp vue3 调用
javascript·vue.js·uni-app
庄园特聘拆椅狂魔1 小时前
Java 后端转全栈的第一课:从前端项目搭建到技术选
java·开发语言·前端
triumph_passion1 小时前
前端路由策略:Memory、Hash 与 History
前端
李剑一1 小时前
AntDesign老版本没有月份和年份区间选择组件?我封装了一个完美版,附源码!
前端·vue.js
牧艺1 小时前
浏览器端 3D 看车重磅升级:从三款展车到可试驾的八车展厅
前端·three.js·交互设计
老男孩游戏时光2 小时前
Electron 桌面应用开发入门,前端也能写客户端
前端