监听元素尺寸变化,你还在用
轮询
或window.resize
?
那你可能已经错过了一个真正为元素尺寸变化而生的原生 API ------ ResizeObserver
,了解一下。
ResizeObserver 到底解决了什么问题?
在 ResizeObserver
出现之前,监听元素尺寸变化只能通过:
window.addEventListener('resize')
- 定时器轮询 DOM 尺寸
- 使用
MutationObserver
搭配逻辑判断 - 借助第三方库
这些方式都存在一个根本问题:它们监听的是"窗口变化"或"DOM结构变化",而非元素自身尺寸变化。
js
// 👎 无法监听特定元素尺寸变化
window.addEventListener('resize', () => {
console.log('窗口变化了,但某个元素变没变不知道');
});
而 ResizeObserver 是专为此生:
js
const ro = new ResizeObserver(entries => {
for (let entry of entries) {
console.log('元素尺寸变化:', entry.contentRect);
}
});
ro.observe(document.querySelector('#target'));
它基于浏览器底层布局机制,异步执行,性能友好,专注监听 DOM 元素尺寸本身。
应用场景

场景一:图表重绘
在容器尺寸变化时重新绘图(比如 ECharts、Highcharts),避免图表被挤压变形。
js
const chart = echarts.init(document.getElementById('chart'));
const ro = new ResizeObserver(() => {
chart.resize();
});
ro.observe(document.getElementById('chart'));
图表容器缩放、切换布局、隐藏再显示等情况,完美支持。无需绑定 window.resize!
场景二:响应式布局组件
如按钮组、菜单、卡片布局等,在容器变窄时切换模式:
ini
ro.observe(container);
ro.callback = entries => {
const width = entries[0].contentRect.width;
toggleLayout(width > 600 ? 'row' : 'column');
};
用 ResizeObserver
替代传统 resize + getBoundingClientRect()
,逻辑更清晰。
场景三:嵌套 iframe、自适应容器等复杂布局
iframe 中的元素尺寸变化,无法通过 window 捕捉,但 ResizeObserver 可以!
- 支持组件嵌套
- 支持 shadow DOM
- 可组合微前端、复杂布局系统
ResizeObserver vs 其他监听方式
功能需求 | ResizeObserver ✅ | window.resize ❌ | MutationObserver ⚠️ | setInterval ❌ |
---|---|---|---|---|
元素尺寸变化监听 | ✅ 支持 | ❌ 不支持 | ⚠️ 需判断尺寸 | ⚠️ 不推荐 |
性能表现 | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐ | ⭐ |
精确度 | 高 | 低 | 中 | 低 |
实时性 | 高 | 中 | 中 | 低 |
编码复杂度 | 低 | 低 | 中 | 高 |
🚀 高阶使用技巧(建议收藏)
1. 防抖处理:控制触发频率
js
const debounce = (fn, delay = 100) => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
};
const ro = new ResizeObserver(debounce(entries => {
// 执行逻辑
}));
适合高频率布局变化场景,比如拖动或动态内容渲染。
2. 多元素监听 + 状态管理
js
const sizeMap = new Map();
const ro = new ResizeObserver(entries => {
for (const entry of entries) {
const old = sizeMap.get(entry.target);
const now = entry.contentRect;
if (!old || old.width !== now.width) {
sizeMap.set(entry.target, now);
handleResize(entry.target);
}
}
});
适合组件列表、自定义容器池、栅格系统。
3. 结合生命周期动态绑定(Vue、React)
js
onMounted(() => {
ro.observe(elRef.value);
});
onBeforeUnmount(() => {
ro.unobserve(elRef.value);
});
Vue / React / Web Component 中建议使用,避免内存泄漏!
总结
总结一句话:ResizeObserver = 更轻量、更精准、更高效的尺寸变化监听方案。但使用时注意:
- 避免在回调中同步读取布局(如
offsetHeight
),防止引发强制回流,造成性能抖动。 - 多元素监听需防抖/节流控制频率,降低回调频率,避免卡顿。
- 组件内要在生命周期正确绑定/解绑,防止内存泄漏。
- IE 不支持,需用 Polyfill 兼容(或者resize-observer-polyfill)。