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

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

相关推荐
阿里小阿希3 分钟前
Vue 3 表单数据缓存架构设计:从问题到解决方案
前端·vue.js·缓存
JefferyXZF34 分钟前
Next.js 核心路由解析:动态路由、路由组、平行路由和拦截路由(四)
前端·全栈·next.js
汪子熙1 小时前
浏览器环境中 window.eval(vOnInit); // csp-ignore-legacy-api 的技术解析与实践意义
前端·javascript
还要啥名字1 小时前
elpis - 动态组件扩展设计
前端
BUG收容所所长1 小时前
🤖 零基础构建本地AI对话机器人:Ollama+React实战指南
前端·javascript·llm
鹏程十八少1 小时前
7. Android RecyclerView吃了80MB内存!KOOM定位+Profiler解剖+MAT验尸全记录
前端
小高0071 小时前
🚀前端异步编程:Promise vs Async/Await,实战对比与应用
前端·javascript·面试
Spider_Man1 小时前
"压"你没商量:性能优化的隐藏彩蛋
javascript·性能优化·node.js
用户87612829073741 小时前
对于通用组件如何获取表单输入,区分表单类型的试验
前端·javascript
所愿ღ1 小时前
Vue框架进阶
前端·vue.js·笔记·前端框架