监听元素宽高变化---new ResizeObserver

参考:ResizeObserver API详解-CSDN博客

有的时候需要监听某个元素的宽高变化,这个时候可以使用JS的  resizeObserver 钩子函数。

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

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

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

兼容性:

完全不兼容ie浏览器,主流浏览器只兼容高版本,基本上2018年以前的浏览器都不兼容,部分浏览器甚至2020年以前都不兼容。

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

回调函数的第一个参数entries是一个数组,数组里有几个对象。

entry.contentRect:被监听元素content的宽高及位置:
  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

entry.borderBoxSize:被监听元素的宽高:
  blockSize: 1000
  inlineSize: 1443

entry.contentBoxSize:被监听元素content部分的宽高:
  blockSize: 600
  inlineSize: 1043

entry.target:被监听的元素
// 监听el-form的宽高
    createResizeObserver(selector) {
        const wrapper = this.$el.querySelector(selector);
        this.observer = new ResizeObserver((entries) => {
          entries.forEach((entry) => {
              this.totalWidth =  entry.contentRect.width; //被监听元素宽
              this.totalHeight = entry.contentRect.height;//被监听元素高
            
          });
          resolve()
        });
        this.observer.observe(wrapper);
    }

this.createResizeObserver("#searchLeft1")

因为 ResizeObserver是异步的,所以会暂时被放到异步任务队列中,等待同步执行完毕后,才回去执行异步函数。如果需要在被监听的元素变化后执行某些操作,可以使用promise处理,如下:
 

createResizeObserver(selector) {
      return new Promise(resolve => {
        const wrapper = this.$el.querySelector(selector);
        this.observer = new ResizeObserver((entries) => {
          entries.forEach((entry) => {
            // for (const entry of entries) {
              this.totalWidth =  entry.contentRect.width;
              this.totalHeight = entry.contentRect.height;
              this.$store.commit("teachResearch/SET_ACTIVEHEIGHT", this.totalHeight); //存储查询条件动态高
            // }
          });
          resolve()//注意resolve的位置
        });
        this.observer.observe(wrapper);
      })
    },

this.createResizeObserver("#searchLeft1").then(()=>{
      // 监听元素大小后,要执行的某些操作
      //XXXXX
    })

取消和结束对目标元素的监听

vue2的写法:
beforeDestroy() {
  resizeObserver.disconnect(this.$refs.wrapper);
},

vue3的写法:
beforeUnmount() {
 resizeObserver.disconnect(this.$refs.wrapper);
}

react的写法:
useEffect(() => {
	return () => {
		resizeObserver.disconnect(this.$refs.wrapper);
	}
},[])

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

节流使用

最后,在使用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)

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值