监听 DIV 元素尺寸变化的几种方法
在 Web 开发中,监听 DOM 元素尺寸变化是一个常见需求。以下是几种实现监听 DIV 长宽变化的方法:
1. 使用 ResizeObserver API(现代推荐方式)
ResizeObserver 是现代浏览器提供的专门用于监听元素尺寸变化的 API。
const divElement = document.getElementById('myDiv');
const observer = new ResizeObserver(entries => {
for (let entry of entries) {
const { width, height } = entry.contentRect;
console.log(`宽度: ${width}px, 高度: ${height}px`);
// 或者获取更精确的尺寸
console.log(`精确宽度: ${entry.contentBoxSize[0].inlineSize}px`);
console.log(`精确高度: ${entry.contentBoxSize[0].blockSize}px`);
}
});
// 开始观察
observer.observe(divElement);
// 停止观察(需要时)
// observer.unobserve(divElement);
React 组件中的使用示例
import { useEffect, useRef } from 'react';
function ResizableDiv() {
const divRef = useRef(null);
useEffect(() => {
const observer = new ResizeObserver(entries => {
const { width, height } = entries[0].contentRect;
console.log('尺寸变化:', width, height);
});
if (divRef.current) {
observer.observe(divRef.current);
}
return () => {
if (divRef.current) {
observer.unobserve(divRef.current);
}
};
}, []);
return <div ref={divRef} style={{ width: '50%', resize: 'both', overflow: 'auto' }}>
可调整大小的DIV
</div>;
}
2. 使用 window.resize 事件(有限场景)
这种方法只适用于窗口大小变化导致元素尺寸变化的情况:
const divElement = document.getElementById('myDiv');
function checkSize() {
const width = divElement.offsetWidth;
const height = divElement.offsetHeight;
console.log(`当前尺寸: ${width}x${height}`);
}
// 初始检查
checkSize();
// 监听窗口大小变化
window.addEventListener('resize', checkSize);
3. 轮询检查(不推荐,仅作备选)
const divElement = document.getElementById('myDiv');
let lastWidth = divElement.offsetWidth;
let lastHeight = divElement.offsetHeight;
setInterval(() => {
const currentWidth = divElement.offsetWidth;
const currentHeight = divElement.offsetHeight;
if (currentWidth !== lastWidth || currentHeight !== lastHeight) {
console.log(`尺寸变化: ${currentWidth}x${currentHeight}`);
lastWidth = currentWidth;
lastHeight = currentHeight;
}
}, 100); // 每100毫秒检查一次
4. 使用 CSS transition 和 transitionend 事件
如果尺寸变化是通过 CSS 动画/过渡实现的:
const divElement = document.getElementById('myDiv');
divElement.addEventListener('transitionend', (event) => {
if (event.propertyName === 'width' || event.propertyName === 'height') {
console.log('尺寸变化完成:',
divElement.offsetWidth,
divElement.offsetHeight
);
}
});
5. 使用第三方库(兼容旧浏览器)
如果需要支持旧版浏览器,可以使用这些库:
-
resize-observer-polyfill
-
element-resize-detector
// 使用 resize-observer-polyfill
import ResizeObserver from 'resize-observer-polyfill';const ro = new ResizeObserver(entries => {
for (let entry of entries) {
console.log('新尺寸:', entry.contentRect.width, entry.contentRect.height);
}
});
ro.observe(document.getElementById('myDiv'));
最佳实践建议
-
优先使用 ResizeObserver - 这是最现代、最高效的方式
-
注意性能 - 在回调函数中避免昂贵操作
-
及时清理 - 组件卸载时取消观察
-
防抖处理 - 如果尺寸变化频繁,考虑添加防抖
完整 React Hook 实现
import { useEffect, useState, useRef } from 'react';
function useElementSize() {
const ref = useRef(null);
const [size, setSize] = useState({
width: 0,
height: 0
});
useEffect(() => {
if (!ref.current) return;
const observer = new ResizeObserver((entries) => {
const { width, height } = entries[0].contentRect;
setSize({ width, height });
});
observer.observe(ref.current);
return () => {
observer.disconnect();
};
}, []);
return [ref, size];
}
// 使用示例
function Component() {
const [divRef, size] = useElementSize();
return (
<div ref={divRef}>
当前尺寸: {size.width} x {size.height}
</div>
);
}
以上方法可以根据你的具体需求和技术环境选择最适合的方案。