概述

在这里插入图片描述

ResizeObserver 是一个 JavaScript API,用于监视元素的大小变化。它可以观察一个或多个 DOM 元素,以便在元素的大小或形状发生变化时触发回调函数。ResizeObserver 是为了更有效地处理元素尺寸变化而引入的,特别适用于响应式设计和自适应布局。

简化尺寸观察:ResizeObserver 提供了一种简单而强大的方法来监视元素的大小变化,而无需使用传统的事件监听器和轮询。

观察多个元素:你可以同时观察多个 DOM 元素,当这些元素的尺寸发生变化时,ResizeObserver 会在每个元素上触发回调函数。

异步回调:ResizeObserver 的回调是异步执行的,这意味着它会在浏览器准备好更新时触发,而不会引发性能问题。

支持容器查询:容器查询是一种在元素的尺寸变化时,根据容器的尺寸来调整元素的布局。ResizeObserver 可以用于实现容器查询的功能。

适应响应式设计:ResizeObserver 对于响应式设计非常有用,可以根据元素的尺寸变化来调整布局,以适应不同的屏幕尺寸和设备。

适用于自定义组件:你可以将 ResizeObserver 集成到自定义组件中,以便在组件内监视子元素的大小变化。

兼容性分析

在这里插入图片描述
完全不兼容ie浏览器,主流浏览器只兼容高版本,基本上2018年以前的浏览器都不兼容,部分浏览器甚至2020年以前都不兼容。

优点分析

而ResizeObserver API就可以帮助我们:监听一个DOM节点的变化,这种变化包括但不仅限于:

1.某个节点的出现和隐藏
2.某个节点的大小变化

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

可以代替

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

用法

ResizeObserver是个构造函数。在使用new关键字调用构造函数,返回实例对象时,需要传入一个回调函数,这个回调用于监听实例对象某个DOM节点的变化

<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: 'ResizeObsever',
  mounted() {
    const myObserver = new ResizeObserver((entries) => {
      entries.forEach((entry) => {
        console.log('被监听元素content的宽高及位置', entry.contentRect)
        // bottom: 700 指top + height的值
        // height: 600 指元素本身的高度,不包含padding,border值
        // left: 100 指padding-left的值
        // right: 1143 指left + width的值
        // top: 100 指padidng-top的值
        // width: 1043  指元素本身的宽度,不包含padding,border值
        // x: 100
        // y: 100
        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)
  }
}
</script>

<style>
.resize-warpper {
  background: skyblue;
}
.resize-element {
  width: calc(100% - 700px);
  background: #ff2d52;
  height: 600px;
  padding: 100px;
  margin: 150px;
  border: 100px solid green;
}

.resize-content {
  width: 100%;
  height: 100%;
  background: yellow;
}
</style>

实例对象myObserver方法除了有observe方法之外,还有disconnect方法和unobserve方法。

disconnect()

取消和结束目标对象上所有对 Element或 SVGElement 观察。

setTimeout(() => {
  resizeObserver.disconnect(this.$refs.wrapper);
}, 4000);

vue2.0中在beforeDestroy 中

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

vue3.0中在beforeUnmount

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

reactHook在useEffect返回的回调中

useEffect(() => {
	return () => {
		resizeObserver.disconnect(this.$refs.wrapper);
	}
},[])

react 在 componentWillUnmount()中

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

unobserve()

结束观察指定的Element或 SVGElement。具体用法与disconnect一致。

节流使用

最后,在使用ResizeObserver API的时候,在每次触发元素的大小变化时,会在1s内触发回调蛮多次的。如果想进一步优化性能,可以加上throttle节流函数处理

const throttle = (fun,delay) => {
	let timer = null;
	return function() {
		const args = arguments
		if(!timer) {
			timer = setTimeout(() => {
				timer = null
			}, delay)
			fun(args )
		}
	}
}

const myObserver = new ResizeObserver(throttle(entries => {
  entries.forEach(entry => {
    console.log('大小位置 contentRect', entry.contentRect)
    console.log('监听的DOM target', entry.target)
  })
}), 500)

myObserver.observe(document.body)
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐