面试题:如何对一个div做监听,监听他的长宽的大小变化

监听 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'));

最佳实践建议

  1. 优先使用 ResizeObserver - 这是最现代、最高效的方式

  2. 注意性能 - 在回调函数中避免昂贵操作

  3. 及时清理 - 组件卸载时取消观察

  4. 防抖处理 - 如果尺寸变化频繁,考虑添加防抖

完整 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>
  );
}

以上方法可以根据你的具体需求和技术环境选择最适合的方案。

相关推荐
数字化顾问6 分钟前
解析前端框架 Axios 的设计理念与源码:从零手写一个支持 HTTP/3 的“类 Axios”最小核
前端
二个半engineer11 分钟前
微前端中iframe集成方式与使用微前端框架方式对比
前端·前端框架
小菜全23 分钟前
《WebAssembly:前端开发的新可能》
前端·javascript
余防28 分钟前
CSRF跨站请求伪造
前端·安全·web安全·csrf
兮山与32 分钟前
前端2.0
前端
南风木兮丶39 分钟前
Vue 项目安装 @antfu/eslint-config 保姆级教程
前端·javascript·vue.js
万少1 小时前
记 HarmonyOS 开发中的一个小事件 怒提华为工单
前端·harmonyos
未来之窗软件服务1 小时前
万象EXCEL开发(六)excel单元格运算逻辑 ——东方仙盟金丹期
前端·excel·仙盟创梦ide·东方仙盟·万象excel
mldong1 小时前
保姆级教程!手把手教你搭建FastAPI + Vue3前后端分离项目
vue.js·python·全栈
Mintopia1 小时前
🚀 Cesium-Kit:10 秒为你的 Cesium 项目添加动态光效标记
前端·javascript·cesium