面试题:如何对一个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>
  );
}

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

相关推荐
深念Y11 小时前
我明白为什么B站没法在浏览器开直播了——Windows Chrome推流踩坑全记录
前端·chrome·webrtc·浏览器·srs·直播·flv
zhangxingchao11 小时前
AI应用开发七:可以替代 RAG 的技术
前端·人工智能·后端
Sun@happy11 小时前
现代 Web 前端渗透——基础篇(1)
前端·web安全
希冀12311 小时前
【CSS学习第十一篇】
前端·css·学习
隔窗听雨眠12 小时前
doctype、charset、meta如何控制整个渲染流水线
java·服务器·前端
kyriewen12 小时前
写组件文档写到吐?我用AI自动生成Storybook,同事以后直接抄
前端·javascript·面试
excel12 小时前
🧠 Prisma 表名大写 vs SQL 导出小写问题深度解析(附踩坑与解决方案)
前端·后端
周淳APP12 小时前
【前端工程化原理通识:从源头到运行时的理论阐述】
前端·编译·打包·前端工程化
五点六六六13 小时前
你敢信这是非Native页面写出来的渐变效果吗🌝(底层原理解析
前端·javascript·面试
tedcloud12313 小时前
TradingAgents部署教程:打造AI量化分析工作流
服务器·前端·人工智能·系统架构·edge