ResizeObserver 是浏览器原生监听元素尺寸变化的 API,能响应 flex/grid、字体加载等引发的重排,而 window.onresize 仅监听窗口大小变化。
ResizeObserver 是什么,为什么不能用 window.onresize 替代
ResizeObserver 是浏览器原生的、专门监听元素尺寸变化的 API,它能响应
、
、
等盒模型变化,包括由 CSS Flex/Grid、
切换、字体加载、甚至
(部分场景)引发的重排。而
只响应窗口大小变化,对内部元素“一无所知”——比如一个
因父容器 flex 增长而变宽,
完全不会触发。
常见错误现象:
– 手动轮询
,CPU 占用高、抖动明显;
– 监听
或
后只测一次,漏掉后续动态变化;
– 用 MutationObserver 监听 class 变化“间接推断”尺寸,逻辑脆弱、覆盖不全。
怎么创建并正确使用 ResizeObserver 实例
必须在目标元素存在且已挂载 DOM 后再实例化,否则会静默失败(不报错但不回调)。观察器本身是异步执行的,回调中拿到的尺寸已是稳定后的最新值,无需额外
或
延迟。
用
创建,
接收两个参数:
(
数组)和
(当前实例)
每个
的
是被观察元素,
提供
/
/
/
等,注意它基于
,不含 padding/border
必须显式调用
开始监听;若元素销毁,应调用
或
避免内存泄漏
哪些尺寸变化它能捕获,哪些不能
它能捕获所有触发 layout(重排)的尺寸变更,但有明确边界:
立即学习
“
前端免费学习笔记(深入)
”;
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
✅ 捕获:
分配导致的宽高变化、
生效、
→
、字体加载完成后的回流、
(仅当元素设了
且用户拖拽)
❌ 不捕获:
(纯绘制层变化,不触发布局)、
、
、
、
(此时元素脱离文档流,
更合适)
⚠️ 注意:
下,
仍只反映 content 区域;如需含 padding,要手动加
等
兼容性与降级方案怎么写才不翻车
Chrome 64+、Firefox 69+、Safari 13.1+ 支持,Edge 79+(即 Chromium 内核后全支持)。IE 完全不支持,且无 polyfill 能 100% 模拟——因为底层依赖 layout 触发机制,JS 无法精确模拟。
安全的降级方式只有两种:
功能渐进增强:核心逻辑不依赖尺寸监听,仅用 ResizeObserver 做“锦上添花”,比如自动调整图表 canvas 大小,降级时保持静态尺寸
轻量轮询兜底(仅限低频场景):
,务必加
清理,且避免在动画帧中高频运行
别试图用
或
事件模拟——它们和尺寸无关,逻辑错位,后期维护成本爆炸。
真正容易被忽略的是:ResizeObserver 回调可能被节流(尤其连续快速 resize 时),但它保证至少触发一次最终状态;如果你需要“每一帧都响应”,说明设计有问题——应该用 CSS 或 requestAnimationFrame 配合 getBoundingClientRect,而不是强求 ResizeObserver。
widthheightborder-boxdisplaytransformwindow.onresizedivwindow.onresizegetBoundingClientRect()DOMContentLoadedloadsetTimeoutrequestAnimationFramenew ResizeObserver(callback)callbackentriesResizeObserverEntryobserverentrytargetcontentRectwidthheighttopleftcontent-boxobserver.observe(element)observer.unobserve(element)observer.disconnect()const ro = new ResizeObserver(entries => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
console.log('尺寸变了:', width, 'x', height);
}
});
ro.observe(document.querySelector('#my-panel'));flexmax-widthvisibility: hiddenvisibleresizeresize: bothtransformopacityfilterwill-changedisplay: noneunobservebox-sizing: border-boxcontentRectgetComputedStyle(target).paddingLeftsetInterval(() => { if (el && el.offsetWidth !== lastW) { /* 处理 */ } }, 250)clearIntervalIntersectionObserverscroll