飞道的博客

ResizeObserver API详解

307人阅读  评论(0)

ResizeObserver API是一个新的JavaScript API,与允许我们去监听某个元素的宽高变化。

兼容性分析


完全不兼容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)

转载:https://blog.csdn.net/glorydx/article/details/116176726
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场