js如何监听元素尺寸变化 检测元素大小变化的3种监听方案!

js如何监听元素尺寸变化 检测元素大小变化的3种监听方案!
最新回答
我们快乐呢

2023-07-10 22:10:08

在 JavaScript 中监听元素尺寸变化,主要有三种方案:ResizeObserverMutationObserver 和传统事件监听(如 window.onresize)。以下是具体实现方法及适用场景:

1. ResizeObserver(现代浏览器首选)

ResizeObserver 是专门为监听元素尺寸变化设计的 API,性能高效且 API 简洁。

  • 基本用法

    const element = document.getElementById('yourElement');const resizeObserver = new ResizeObserver(entries => { for (let entry of entries) { const width = entry.contentRect.width; const height = entry.contentRect.height; console.log(`Element's new size: width=${width}, height=${height}`); }});resizeObserver.observe(element);// 停止监听// resizeObserver.unobserve(element);// resizeObserver.disconnect();
  • 优势

    高效:仅在元素尺寸变化时触发回调。

    简单易用:API 设计直观。

    针对性强:专为监听元素尺寸变化设计。

  • 兼容性

    需考虑浏览器兼容性(可通过

    Can I Use
    查询)。

    不支持旧版浏览器时需使用备选方案。

2. MutationObserver(兼容旧浏览器的备选方案)

MutationObserver 可监听 DOM 属性变化,通过过滤 style 属性变化间接实现尺寸监听。

  • 基本用法

    const element = document.getElementById('yourElement');const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.type === 'attributes' && mutation.attributeName === 'style') { const width = element.offsetWidth; const height = element.offsetHeight; console.log(`Element's size changed: width=${width}, height=${height}`); } });});observer.observe(element, { attributes: true, attributeFilter: ['style'] // 仅监听 style 属性变化});// 停止监听// observer.disconnect();
  • 缺点

    性能较差:需监听所有属性变化后过滤。

    复杂性高:使用逻辑比 ResizeObserver 复杂。

  • 适用场景

    需兼容旧浏览器且对性能要求不高。

    需同时监听其他 DOM 变化(如属性、子节点)。

3. 传统事件监听(兼容性最好)

通过 window.onresize 监听窗口大小变化,间接判断元素尺寸变化。

  • 基本用法

    window.onresize = () => { const element = document.getElementById('yourElement'); const width = element.offsetWidth; const height = element.offsetHeight; console.log(`Element's size changed: width=${width}, height=${height}`);};
  • 缺点

    性能问题:每次窗口变化均触发回调,即使元素尺寸未变。

    全局性:监听窗口而非特定元素。

  • 适用场景

    需兼容所有浏览器。

    仅需在窗口变化时执行全局操作。

方案选择建议
  • 优先选择 ResizeObserver:若无需兼容旧浏览器,其高效性和针对性最优。
  • 备选 MutationObserver:需兼容旧浏览器且性能要求不高时使用。
  • 传统事件监听:仅在必须兼容所有浏览器且操作全局时使用。
处理频繁尺寸变化

若元素尺寸变化频繁,可通过节流(throttle)防抖(debounce)优化性能:

  • 节流示例

    function throttle(func, delay) { let timeoutId; let lastExecTime = 0; return function(...args) { const currentTime = Date.now(); if (!timeoutId) { if (currentTime - lastExecTime >= delay) { func.apply(this, args); lastExecTime = currentTime; } else { timeoutId = setTimeout(() => { func.apply(this, args); timeoutId = null; lastExecTime = Date.now(); }, delay - (currentTime - lastExecTime)); } } };}const throttledResizeObserver = new ResizeObserver(throttle(entries => { console.log("Throttled resize event");}, 200)); // 200ms 节流
  • 防抖示例

    function debounce(func, delay) { let timeoutId; return function(...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => { func.apply(this, args); }, delay); };}const debouncedResizeObserver = new ResizeObserver(debounce(entries => { console.log("Debounced resize event");}, 200)); // 200ms 防抖
总结
  • 现代项目:优先使用 ResizeObserver。
  • 兼容旧浏览器:选择 MutationObserver 或传统事件监听。
  • 性能优化:对频繁变化使用节流或防抖。