ResizeObserver

402 阅读2分钟

ResizeObserver介绍

  • ResizeObserver 是一个 JavaScript API,用于监视元素的大小变化。它可以观察一个或多个元素,以便在元素的大小或形状发生变化时触发回调函数。ResizeObserver 是为了更有效地处理元素尺寸变化而引入的,特别适用于响应式设计和自适应布局。
  • 简化尺寸观察:ResizeObserver 提供了一种简单而强大的方法来监视元素的大小变化,而无需使用传统的事件监听器和轮询。
  • 观察多个元素:你可以同时观察多个 DOM 元素,当这些元素的尺寸发生变化时,ResizeObserver 会在每个元素上触发。
  • 异步回调:ResizeObserver 的回调是异步执行的,这意味着它会在浏览器准备好更新时触发,而不会引发性能问题。
  • 支持容器查询:容器查询是一种在元素的尺寸变化时,根据容器的尺寸来调整元素的布局。ResizeObserver 可以用于实现容器查询的功能。

ResizeObserver API就可以帮助我们:监听一个DOM节点的变化,这种变化如:

  • 某个节点的出现和隐藏。
  • 某个节点的大小变化。

ResizeObserver避免了在自身回调中调整大小,从而触发的无限回调和循环依赖。它仅通过在后续帧中处理DOM中更深层次的元素来实现这一点。如果(浏览器)遵循规范,只会在绘制前或布局后触发调用。

可以代替:

window.onresize = function() {
  // SomeJavaScriptCode
};

具体用法

vue2

<template>
  <div class="resize-warpper">
    margin
    <div class="resize-element" ref="wrapper">
      padding
      <div class="resize-content">content</div>
    </div>
    margin
  </div>
</template>

<script>
export default {
  name: 'ResizeObserver',
  data() {
    return {

    }
  },
  mounted() {
    const myObserver  = new ResizeObserver((entries) => {
      entries.forEach(entry => {
        console.log('真实dom元素',entry.target)
        console.log('被监听元素content的宽高及位置', entry.contentRect)
        // bottom:  指top + height的值
        // height:  指元素本身的高度,不包含padding,border值
        // left: 指padding-left的值
        // right: 指left + width的值
        // top:  指padidng-top的值
        // width: 指元素本身的宽度,不包含padding,border值
        // x: 元素内容区域左边缘相对于视口或包含块的水平偏移量。
        // y: 元素内容区域顶边相对于视口或包含块的垂直偏移量。
        console.log('被监听元素的宽高', entry.borderBoxSize)
        // blockSize: 1000
        // inlineSize: 1443
        console.log('被监听元素content部分的宽高', entry.contentBoxSize)
        // blockSize: 600
        // inlineSize: 1043
        console.log('被监听元素', entry.target)
      })
    })
    myObserver .observe(this.$refs.wrapper)
  },
  methods: {

  }
}
</script>

<style lang="less" scoped>

</style>

其它实例方法

ResizeObserver 接口的 disconnect() 方法取消所有的对 Element 或 SVGElement 目标的监听。 ResizeObserver 接口的 unobserve() 方法结束对指定的 Element 或 SVGElement 的监听。 在vue2中,可以:

beforeDestroy() {
  resizeObserver.disconnect(this.$refs.wrapper);
}

组件源码

import ResizeObserver from 'resize-observer-polyfill'; // 为了更好的兼容性

const resizeHandler = function(entries) {
  for (let entry of entries) {
    const listeners = entry.target.__resizeListeners__ || [];
    if (listeners.length) {
      listeners.forEach(fn => {
        fn();
      });
    }
  }
};

/* istanbul ignore next */
export const addResizeListener = function(element, fn) {
  if (isServer) return;
  if (!element.__resizeListeners__) {
    element.__resizeListeners__ = [];
    element.__ro__ = new ResizeObserver(debounce(16, resizeHandler));
    element.__ro__.observe(element);
  }
  element.__resizeListeners__.push(fn);
};

/* istanbul ignore next */
export const removeResizeListener = function(element, fn) {
  if (!element || !element.__resizeListeners__) return;
  element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
  if (!element.__resizeListeners__.length) {
    element.__ro__.disconnect();
  }
};