详细讲解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 小时前
受够了 AI 写完代码留下一堆端口?我做了一个端口管理App!
前端·macos·vibecoding
Xuepoo2 小时前
我抛弃了 DOM,但保留了无障碍访问
前端
李明卫杭州2 小时前
Vue2 vs Vue3 的 h 函数:渲染函数完整迁移指南
前端
月光刺眼2 小时前
用LangChain 打造第一个 Agent:LLM 大脑与 Tool 手脚的完整闭环
javascript·人工智能·全栈
星栈2 小时前
LiveView 的认证系统:从登录到权限,我一开始以为有 `current_user` 就算完事了
前端·前端框架·elixir
在因斯坦2 小时前
摸摸鱼之前端自己研究 Jenkins 自动化部署
前端
西西学代码2 小时前
Flutter---底部导航栏(2)
开发语言·javascript·flutter
snpgroupcn3 小时前
SAP实施风险管控注意事项:四大风险域与防范策略
前端·数据库·人工智能
阿成学长_Cain3 小时前
Linux talk 命令详解:经典终端实时聊天工具,无需图形界面即可对话
linux·运维·前端
lichenyang4534 小时前
从零开始写 HarmonyOS Web 容器:先让 ArkWeb 加载本地 H5
前端